@ -117,8 +117,8 @@ static const OptionDef options[];
# define MAX_STREAMS 1024 /* arbitrary sanity check value */
static const char * last_asked_format = NULL ;
static double * input_files_ ts_scale[ MAX_FILES ] = { NULL } ;
static int nb_input_files_ ts_scale [ MAX_FILES ] = { 0 } ;
static double * ts_scale ;
static int nb_ts_scale ;
static AVFormatContext * output_files [ MAX_FILES ] ;
static int nb_output_files = 0 ;
@ -171,7 +171,6 @@ static char *vfilters = NULL;
static int intra_only = 0 ;
static int audio_sample_rate = 0 ;
static int64_t channel_layout = 0 ;
# define QSCALE_NONE -99999
static float audio_qscale = QSCALE_NONE ;
static int audio_disable = 0 ;
@ -194,7 +193,6 @@ static float mux_max_delay= 0.7;
static int64_t recording_time = INT64_MAX ;
static int64_t start_time = 0 ;
static int64_t recording_timestamp = 0 ;
static int64_t input_ts_offset = 0 ;
static int file_overwrite = 0 ;
static AVDictionary * metadata ;
@ -327,6 +325,7 @@ typedef struct InputStream {
int64_t next_pts ; /* synthetic pts for cases where pkt.pts
is not defined */
int64_t pts ; /* current pts */
double ts_scale ;
int is_start ; /* is 1 at the start and after a discontinuity */
int showed_multi_packet_warning ;
int is_past_recording_time ;
@ -538,7 +537,6 @@ static int ffmpeg_exit(int ret)
}
for ( i = 0 ; i < nb_input_files ; i + + ) {
av_close_input_file ( input_files [ i ] . ctx ) ;
av_free ( input_files_ts_scale [ i ] ) ;
}
av_free ( intra_matrix ) ;
@ -671,10 +669,16 @@ static void choose_pixel_fmt(AVStream *st, AVCodec *codec)
}
}
static OutputStream * new_output_stream ( AVFormatContext * oc , int file_idx )
static OutputStream * new_output_stream ( AVFormatContext * oc , int file_idx , AVCodec * codec )
{
int idx = oc - > nb_streams - 1 ;
OutputStream * ost ;
AVStream * st = av_new_stream ( oc , oc - > nb_streams < nb_streamid_map ? streamid_map [ oc - > nb_streams ] : 0 ) ;
int idx = oc - > nb_streams - 1 ;
if ( ! st ) {
av_log ( NULL , AV_LOG_ERROR , " Could not alloc stream. \n " ) ;
ffmpeg_exit ( 1 ) ;
}
output_streams_for_file [ file_idx ] =
grow_array ( output_streams_for_file [ file_idx ] ,
@ -689,6 +693,10 @@ static OutputStream *new_output_stream(AVFormatContext *oc, int file_idx)
}
ost - > file_index = file_idx ;
ost - > index = idx ;
ost - > st = st ;
ost - > enc = codec ;
avcodec_get_context_defaults3 ( st - > codec , codec ) ;
ost - > sws_flags = av_get_int ( sws_opts , " sws_flags " , NULL ) ;
return ost ;
@ -704,28 +712,21 @@ static int read_ffserver_streams(AVFormatContext *s, const char *filename)
if ( err < 0 )
return err ;
/* copy stream format */
s - > nb_streams = 0 ;
s - > streams = av_mallocz ( sizeof ( AVStream * ) * ic - > nb_streams ) ;
for ( i = 0 ; i < ic - > nb_streams ; i + + ) {
AVStream * st ;
OutputStream * ost ;
AVCodec * codec ;
s - > nb_streams + + ;
codec = avcodec_find_encoder ( ic - > streams [ i ] - > codec - > codec_id ) ;
ost = new_output_stream ( s , nb_output_files , codec ) ;
st = ost - > st ;
// FIXME: a more elegant solution is needed
st = av_mallocz ( sizeof ( AVStream ) ) ;
memcpy ( st , ic - > streams [ i ] , sizeof ( AVStream ) ) ;
st - > info = av_malloc ( sizeof ( * st - > info ) ) ;
memcpy ( st - > info , ic - > streams [ i ] - > info , sizeof ( * st - > info ) ) ;
st - > codec = avcodec_alloc_context ( ) ;
if ( ! st - > codec ) {
print_error ( filename , AVERROR ( ENOMEM ) ) ;
ffmpeg_exit ( 1 ) ;
}
avcodec_copy_context ( st - > codec , ic - > streams [ i ] - > codec ) ;
s - > streams [ i ] = st ;
codec = avcodec_find_encoder ( st - > codec - > codec_id ) ;
if ( st - > codec - > codec_type = = AVMEDIA_TYPE_AUDIO ) {
if ( audio_stream_copy ) {
st - > stream_copy = 1 ;
@ -740,13 +741,8 @@ static int read_ffserver_streams(AVFormatContext *s, const char *filename)
if ( st - > codec - > flags & CODEC_FLAG_BITEXACT )
nopts = 1 ;
new_output_stream ( s , nb_output_files ) ;
}
if ( ! nopts )
s - > timestamp = av_gettime ( ) ;
av_close_input_file ( ic ) ;
return 0 ;
}
@ -2102,7 +2098,6 @@ static int transcode(AVFormatContext **output_files,
for ( i = 0 ; i < os - > nb_streams ; i + + , n + + ) {
int found ;
ost = ost_table [ n ] = output_streams_for_file [ k ] [ i ] ;
ost - > st = os - > streams [ i ] ;
if ( nb_stream_maps > 0 ) {
ost - > source_index = input_files [ stream_maps [ n ] . file_index ] . ist_index +
stream_maps [ n ] . stream_index ;
@ -2278,6 +2273,9 @@ static int transcode(AVFormatContext **output_files,
}
choose_sample_rate ( ost - > st , ost - > enc ) ;
codec - > time_base = ( AVRational ) { 1 , codec - > sample_rate } ;
if ( codec - > sample_fmt = = AV_SAMPLE_FMT_NONE )
codec - > sample_fmt = icodec - > sample_fmt ;
choose_sample_fmt ( ost - > st , ost - > enc ) ;
if ( ! codec - > channels ) {
codec - > channels = icodec - > channels ;
codec - > channel_layout = icodec - > channel_layout ;
@ -2738,12 +2736,11 @@ static int transcode(AVFormatContext **output_files,
if ( pkt . pts ! = AV_NOPTS_VALUE )
pkt . pts + = av_rescale_q ( input_files [ ist - > file_index ] . ts_offset , AV_TIME_BASE_Q , ist - > st - > time_base ) ;
if ( pkt . stream_index < nb_input_files_ts_scale [ file_index ]
& & input_files_ts_scale [ file_index ] [ pkt . stream_index ] ) {
if ( ist - > ts_scale ) {
if ( pkt . pts ! = AV_NOPTS_VALUE )
pkt . pts * = input_files_ts_scale [ file_index ] [ pkt . stream_index ] ;
pkt . pts * = ist - > ts_scale ;
if ( pkt . dts ! = AV_NOPTS_VALUE )
pkt . dts * = input_files_ts_scale [ file_index ] [ pkt . stream_index ] ;
pkt . dts * = ist - > ts_scale ;
}
// fprintf(stderr, "next:%"PRId64" dts:%"PRId64" off:%"PRId64" %d\n", ist->next_pts, pkt.dts, input_files[ist->file_index].ts_offset, ist->st->codec->codec_type);
@ -3203,8 +3200,8 @@ static int opt_input_ts_scale(const char *opt, const char *arg)
if ( stream > = MAX_STREAMS )
ffmpeg_exit ( 1 ) ;
input_files_ ts_scale[ nb_input_files ] = grow_array ( input_files_ ts_scale[ nb_input_files ] , sizeof ( * input_files_ ts_scale[ nb_input_files ] ) , & nb_input_files_ ts_scale [ nb_input_files ] , stream + 1 ) ;
input_files_ ts_scale[ nb_input_files ] [ stream ] = scale ;
ts_scale = grow_array ( ts_scale , sizeof ( * ts_scale ) , & nb_ts_scale , stream + 1 ) ;
ts_scale [ stream ] = scale ;
return 0 ;
}
@ -3222,7 +3219,14 @@ static int opt_start_time(const char *opt, const char *arg)
static int opt_recording_timestamp ( const char * opt , const char * arg )
{
recording_timestamp = parse_time_or_die ( opt , arg , 0 ) / 1000000 ;
char buf [ 128 ] ;
int64_t recording_timestamp = parse_time_or_die ( opt , arg , 0 ) / 1E6 ;
struct tm time = * gmtime ( ( time_t * ) & recording_timestamp ) ;
strftime ( buf , sizeof ( buf ) , " creation_time=%FT%T%z " , & time ) ;
opt_metadata ( " metadata " , buf ) ;
av_log ( NULL , AV_LOG_WARNING , " %s is deprecated, set the 'creation_time' metadata "
" tag instead. \n " , opt ) ;
return 0 ;
}
@ -3401,14 +3405,15 @@ static int opt_input_file(const char *opt, const char *filename)
ist - > file_index = nb_input_files ;
ist - > discard = 1 ;
if ( i < nb_ts_scale )
ist - > ts_scale = ts_scale [ i ] ;
switch ( dec - > codec_type ) {
case AVMEDIA_TYPE_AUDIO :
ist - > dec = avcodec_find_decoder_by_name ( audio_codec_name ) ;
if ( ! ist - > dec )
ist - > dec = avcodec_find_decoder ( dec - > codec_id ) ;
set_context_opts ( dec , avcodec_opts [ AVMEDIA_TYPE_AUDIO ] , AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM , ist - > dec ) ;
channel_layout = dec - > channel_layout ;
audio_sample_fmt = dec - > sample_fmt ;
if ( audio_disable )
st - > discard = AVDISCARD_ALL ;
break ;
@ -3475,6 +3480,9 @@ static int opt_input_file(const char *opt, const char *filename)
frame_width = 0 ;
audio_sample_rate = 0 ;
audio_channels = 0 ;
audio_sample_fmt = AV_SAMPLE_FMT_NONE ;
av_freep ( & ts_scale ) ;
nb_ts_scale = 0 ;
av_freep ( & video_codec_name ) ;
av_freep ( & audio_codec_name ) ;
@ -3535,23 +3543,20 @@ static void new_video_stream(AVFormatContext *oc, int file_idx)
enum CodecID codec_id = CODEC_ID_NONE ;
AVCodec * codec = NULL ;
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 ) ;
if ( ! video_stream_copy ) {
if ( video_codec_name ) {
codec_id = find_codec_or_die ( video_codec_name , AVMEDIA_TYPE_VIDEO , 1 ,
avcodec_opts [ AVMEDIA_TYPE_VIDEO ] - > strict_std_compliance ) ;
codec = avcodec_find_encoder_by_name ( video_codec_name ) ;
ost - > enc = codec ;
} else {
codec_id = av_guess_codec ( oc - > oformat , NULL , oc - > filename , NULL , AVMEDIA_TYPE_VIDEO ) ;
codec = avcodec_find_encoder ( codec_id ) ;
}
}
ost = new_output_stream ( oc , file_idx , codec ) ;
st = ost - > st ;
if ( ! video_stream_copy ) {
ost - > frame_aspect_ratio = frame_aspect_ratio ;
frame_aspect_ratio = 0 ;
# if CONFIG_AVFILTER
@ -3560,7 +3565,6 @@ static void new_video_stream(AVFormatContext *oc, int file_idx)
# endif
}
avcodec_get_context_defaults3 ( st - > codec , codec ) ;
ost - > bitstream_filters = video_bitstream_filters ;
video_bitstream_filters = NULL ;
@ -3674,26 +3678,18 @@ static void new_audio_stream(AVFormatContext *oc, int file_idx)
AVCodecContext * audio_enc ;
enum CodecID codec_id = CODEC_ID_NONE ;
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 ) ;
if ( ! audio_stream_copy ) {
if ( audio_codec_name ) {
codec_id = find_codec_or_die ( audio_codec_name , AVMEDIA_TYPE_AUDIO , 1 ,
avcodec_opts [ AVMEDIA_TYPE_AUDIO ] - > strict_std_compliance ) ;
codec = avcodec_find_encoder_by_name ( audio_codec_name ) ;
ost - > enc = codec ;
} else {
codec_id = av_guess_codec ( oc - > oformat , NULL , oc - > filename , NULL , AVMEDIA_TYPE_AUDIO ) ;
codec = avcodec_find_encoder ( codec_id ) ;
}
}
avcodec_get_context_defaults3 ( st - > codec , codec ) ;
ost = new_output_stream ( oc , file_idx , codec ) ;
st = ost - > st ;
ost - > bitstream_filters = audio_bitstream_filters ;
audio_bitstream_filters = NULL ;
@ -3722,11 +3718,10 @@ static void new_audio_stream(AVFormatContext *oc, int file_idx)
}
if ( audio_channels )
audio_enc - > channels = audio_channels ;
audio_enc - > sample_fmt = audio_sample_fmt ;
if ( audio_sample_fmt ! = AV_SAMPLE_FMT_NONE )
audio_enc - > sample_fmt = audio_sample_fmt ;
if ( audio_sample_rate )
audio_enc - > sample_rate = audio_sample_rate ;
audio_enc - > channel_layout = channel_layout ;
choose_sample_fmt ( st , codec ) ;
}
if ( audio_language ) {
av_dict_set ( & st - > metadata , " language " , audio_language , 0 ) ;
@ -3742,21 +3737,16 @@ static void new_audio_stream(AVFormatContext *oc, int file_idx)
static void new_data_stream ( AVFormatContext * oc , int file_idx )
{
AVStream * st ;
AVCodec * codec = NULL ;
OutputStream * ost ;
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 ) ;
}
new_output_stream ( oc , file_idx ) ;
ost = new_output_stream ( oc , file_idx , NULL ) ;
st = ost - > st ;
data_enc = st - > codec ;
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 ;
@ -3784,25 +3774,19 @@ static void new_subtitle_stream(AVFormatContext *oc, int file_idx)
AVCodecContext * subtitle_enc ;
enum CodecID codec_id = CODEC_ID_NONE ;
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 ) ;
subtitle_enc = st - > codec ;
if ( ! subtitle_stream_copy ) {
if ( subtitle_codec_name ) {
codec_id = find_codec_or_die ( subtitle_codec_name , AVMEDIA_TYPE_SUBTITLE , 1 ,
avcodec_opts [ AVMEDIA_TYPE_SUBTITLE ] - > strict_std_compliance ) ;
codec = avcodec_find_encoder_by_name ( subtitle_codec_name ) ;
ost - > enc = codec ;
} else {
codec_id = av_guess_codec ( oc - > oformat , NULL , oc - > filename , NULL , AVMEDIA_TYPE_SUBTITLE ) ;
codec = avcodec_find_encoder ( codec_id ) ;
}
}
avcodec_get_context_defaults3 ( st - > codec , codec ) ;
ost = new_output_stream ( oc , file_idx , codec ) ;
st = ost - > st ;
subtitle_enc = st - > codec ;
ost - > bitstream_filters = subtitle_bitstream_filters ;
subtitle_bitstream_filters = NULL ;
@ -3938,8 +3922,6 @@ static int opt_output_file(const char *opt, const char *filename)
if ( use_subtitle ) new_subtitle_stream ( oc , nb_output_files ) ;
if ( use_data ) new_data_stream ( oc , nb_output_files ) ;
oc - > timestamp = recording_timestamp ;
av_dict_copy ( & oc - > metadata , metadata , 0 ) ;
av_dict_free ( & metadata ) ;
}
@ -4005,6 +3987,7 @@ static int opt_output_file(const char *opt, const char *filename)
frame_height = 0 ;
audio_sample_rate = 0 ;
audio_channels = 0 ;
audio_sample_fmt = AV_SAMPLE_FMT_NONE ;
av_freep ( & forced_key_frames ) ;
uninit_opts ( ) ;