2001-07-22 16:37:44 +02:00
/*
2003-06-07 20:34:02 +02:00
* Copyright ( c ) 2000 - 2003 Fabrice Bellard
2001-07-22 16:37:44 +02:00
*
2006-10-07 17:30:46 +02:00
* This file is part of FFmpeg .
*
* FFmpeg is free software ; you can redistribute it and / or
2002-05-26 00:25:13 +02:00
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
2006-10-07 17:30:46 +02:00
* version 2.1 of the License , or ( at your option ) any later version .
2001-07-22 16:37:44 +02:00
*
2006-10-07 17:30:46 +02:00
* FFmpeg is distributed in the hope that it will be useful ,
2001-07-22 16:37:44 +02:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
2002-05-26 00:25:13 +02:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
2001-07-22 16:37:44 +02:00
*
2002-05-26 00:25:13 +02:00
* You should have received a copy of the GNU Lesser General Public
2006-10-07 17:30:46 +02:00
* License along with FFmpeg ; if not , write to the Free Software
2006-01-12 23:43:26 +01:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2001-07-22 16:37:44 +02:00
*/
2007-06-10 16:34:56 +02:00
2011-12-22 10:23:22 +01:00
/**
* @ file
* multimedia converter based on the FFmpeg libraries
*/
2007-07-02 09:43:23 +02:00
# include "config.h"
# include <ctype.h>
# include <string.h>
# include <math.h>
# include <stdlib.h>
# include <errno.h>
2006-11-22 13:15:58 +01:00
# include <signal.h>
2004-05-12 18:51:39 +02:00
# include <limits.h>
2008-08-15 00:01:59 +02:00
# include <unistd.h>
2008-05-09 13:56:36 +02:00
# include "libavformat/avformat.h"
# include "libavdevice/avdevice.h"
# include "libswscale/swscale.h"
2011-02-03 14:58:59 +01:00
# include "libavutil/opt.h"
2008-07-31 15:11:07 +02:00
# include "libavcodec/audioconvert.h"
2011-02-07 14:37:08 +01:00
# include "libavutil/audioconvert.h"
# include "libavutil/parseutils.h"
# include "libavutil/samplefmt.h"
2010-07-01 20:49:44 +02:00
# include "libavutil/colorspace.h"
2008-05-09 13:56:36 +02:00
# include "libavutil/fifo.h"
2010-10-31 23:48:44 +01:00
# include "libavutil/intreadwrite.h"
2011-05-22 12:46:29 +02:00
# include "libavutil/dict.h"
2011-06-04 13:58:23 +02:00
# include "libavutil/mathematics.h"
2010-01-30 20:10:26 +01:00
# include "libavutil/pixdesc.h"
2008-05-09 13:56:36 +02:00
# include "libavutil/avstring.h"
2010-03-09 16:10:23 +01:00
# include "libavutil/libm.h"
2011-12-26 03:35:54 +01:00
# include "libavutil/imgutils.h"
2008-05-09 13:56:36 +02:00
# include "libavformat/os_support.h"
2011-09-19 06:13:30 +02:00
# include "libswresample/swresample.h"
2001-08-16 00:29:44 +02:00
2011-04-09 03:09:49 +02:00
# include "libavformat/ffm.h" // not public API
2010-05-07 11:43:21 +02:00
# if CONFIG_AVFILTER
2011-05-01 14:47:05 +02:00
# include "libavfilter / avcodec.h"
2010-05-07 11:43:21 +02:00
# include "libavfilter / avfilter.h"
# include "libavfilter / avfiltergraph.h"
2011-09-06 18:37:44 +02:00
# include "libavfilter / buffersink.h"
2011-12-26 03:35:54 +01:00
# include "libavfilter / buffersrc.h"
2010-05-07 11:43:21 +02:00
# include "libavfilter / vsrc_buffer.h"
# endif
2009-01-14 00:44:16 +01:00
# if HAVE_SYS_RESOURCE_H
2008-05-11 13:17:23 +02:00
# include <sys/types.h>
2010-02-22 23:21:58 +01:00
# include <sys/time.h>
2008-05-08 02:44:42 +02:00
# include <sys/resource.h>
2009-01-14 00:44:16 +01:00
# elif HAVE_GETPROCESSTIMES
2007-07-13 18:11:36 +02:00
# include <windows.h>
# endif
2010-02-22 23:21:58 +01:00
# if HAVE_GETPROCESSMEMORYINFO
# include <windows.h>
# include <psapi.h>
# endif
2007-07-13 18:11:36 +02:00
2009-01-14 00:44:16 +01:00
# if HAVE_SYS_SELECT_H
2008-09-26 04:13:38 +02:00
# include <sys/select.h>
# endif
2011-03-30 20:58:13 +02:00
# if HAVE_TERMIOS_H
# include <fcntl.h>
# include <sys/ioctl.h>
# include <sys/time.h>
# include <termios.h>
# elif HAVE_KBHIT
2007-07-11 16:07:55 +02:00
# include <conio.h>
2001-08-13 23:43:02 +02:00
# endif
2002-05-26 00:25:13 +02:00
# include <time.h>
2001-07-22 16:37:44 +02:00
2003-06-07 20:34:02 +02:00
# include "cmdutils.h"
2010-10-01 15:55:13 +02:00
# include "libavutil/avassert.h"
2004-09-22 19:50:53 +02:00
2012-01-05 02:03:12 +01:00
# define VSYNC_AUTO -1
# define VSYNC_PASSTHROUGH 0
# define VSYNC_CFR 1
# define VSYNC_VFR 2
2011-04-23 15:19:17 +02:00
const char program_name [ ] = " ffmpeg " ;
2008-05-29 10:48:51 +02:00
const int program_birth_year = 2000 ;
2007-09-27 08:38:40 +02:00
2001-07-22 16:37:44 +02:00
/* select an input stream for an output stream */
2011-06-23 19:14:08 +02:00
typedef struct StreamMap {
2011-08-30 04:06:24 +02:00
int disabled ; /** 1 is this mapping is disabled by a negative map */
2001-07-22 16:37:44 +02:00
int file_index ;
int stream_index ;
2005-05-26 10:59:05 +02:00
int sync_file_index ;
int sync_stream_index ;
2011-06-23 19:14:08 +02:00
} StreamMap ;
2001-07-22 16:37:44 +02:00
2011-11-04 18:54:01 +01:00
typedef struct {
int file_idx , stream_idx , channel_idx ; // input
int ofile_idx , ostream_idx ; // output
} AudioChannelMap ;
2010-09-24 17:40:53 +02:00
/**
* select an input file for an output file
*/
2011-06-23 19:14:08 +02:00
typedef struct MetadataMap {
2011-08-05 01:18:07 +02:00
int file ; ///< file index
char type ; ///< type of metadata to copy -- (g)lobal, (s)tream, (c)hapter or (p)rogram
int index ; ///< stream/chapter/program number
2011-06-23 19:14:08 +02:00
} MetadataMap ;
2004-07-21 03:35:32 +02:00
2008-05-01 17:12:00 +02:00
static const OptionDef options [ ] ;
2001-07-22 16:37:44 +02:00
2010-10-01 23:56:09 +02:00
# define MAX_STREAMS 1024 /* arbitrary sanity check value */
2010-11-12 07:56:19 +01:00
2011-04-03 02:14:00 +02:00
static int frame_bits_per_raw_sample = 0 ;
2005-03-17 02:25:01 +01:00
static int video_discard = 0 ;
2011-08-30 01:46:34 +02:00
static int same_quant = 0 ;
2001-08-11 20:58:18 +02:00
static int do_deinterlace = 0 ;
2004-06-05 23:08:45 +02:00
static int intra_dc_precision = 8 ;
2006-07-13 23:13:49 +02:00
static int loop_input = 0 ;
2005-06-18 03:52:24 +02:00
static int loop_output = AVFMT_NOOUTPUTLOOP ;
2005-12-18 21:01:02 +01:00
static int qp_hist = 0 ;
2001-07-22 16:37:44 +02:00
static int intra_only = 0 ;
2011-09-12 12:02:41 +02:00
static const char * video_codec_name = NULL ;
static const char * audio_codec_name = NULL ;
static const char * subtitle_codec_name = NULL ;
2001-07-22 16:37:44 +02:00
static int file_overwrite = 0 ;
2011-11-24 21:42:42 +01:00
static int no_file_overwrite = 0 ;
2001-07-31 01:19:22 +02:00
static int do_benchmark = 0 ;
2001-09-23 19:14:51 +02:00
static int do_hex_dump = 0 ;
2003-11-10 19:54:17 +01:00
static int do_pkt_dump = 0 ;
2011-11-09 18:58:07 +01:00
static int do_psnr = 0 ;
2002-10-10 19:09:01 +02:00
static int do_pass = 0 ;
2011-04-21 00:46:20 +02:00
static const char * pass_logfilename_prefix ;
2012-01-05 02:03:12 +01:00
static int video_sync_method = VSYNC_AUTO ;
2011-12-30 03:46:24 +01:00
static int audio_sync_method = 0 ;
static float audio_drift_threshold = 0.1 ;
static int copy_ts = 0 ;
static int copy_tb = - 1 ;
2008-12-14 16:02:27 +01:00
static int opt_shortest = 0 ;
2007-04-25 15:55:11 +02:00
static char * vstats_filename ;
2007-09-06 22:11:02 +02:00
static FILE * vstats_file ;
2002-10-10 19:09:01 +02:00
2005-03-23 03:10:23 +01:00
static int audio_volume = 256 ;
2003-01-22 23:40:52 +01:00
2008-09-05 01:23:44 +02:00
static int exit_on_error = 0 ;
2003-08-29 22:51:10 +02:00
static int using_stdin = 0 ;
2011-04-22 18:49:44 +02:00
static int run_as_daemon = 0 ;
2011-10-08 17:21:25 +02:00
static volatile int received_nb_signals = 0 ;
2004-04-15 15:57:55 +02:00
static int64_t video_size = 0 ;
static int64_t audio_size = 0 ;
static int64_t extra_size = 0 ;
2004-06-12 00:03:16 +02:00
static int nb_frames_dup = 0 ;
static int nb_frames_drop = 0 ;
2004-06-18 05:03:32 +02:00
static int input_sync ;
2003-08-29 22:51:10 +02:00
2007-08-07 02:26:37 +02:00
static float dts_delta_threshold = 10 ;
2004-11-11 19:09:28 +01:00
2011-10-10 03:41:49 +02:00
static int print_stats = 1 ;
2005-09-11 13:10:25 +02:00
2009-04-13 05:55:26 +02:00
static uint8_t * audio_buf ;
static uint8_t * audio_out ;
2011-01-25 00:36:17 +01:00
static unsigned int allocated_audio_out_size , allocated_audio_buf_size ;
2009-04-13 05:55:26 +02:00
2011-09-02 00:16:19 +02:00
static uint8_t * input_tmp = NULL ;
2008-12-26 20:25:24 +01:00
# define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
2001-07-22 16:37:44 +02:00
2011-12-26 03:35:54 +01:00
typedef struct FrameBuffer {
uint8_t * base [ 4 ] ;
uint8_t * data [ 4 ] ;
int linesize [ 4 ] ;
int h , w ;
enum PixelFormat pix_fmt ;
int refcount ;
struct InputStream * ist ;
struct FrameBuffer * next ;
} FrameBuffer ;
2011-08-30 15:44:47 +02:00
typedef struct InputStream {
int file_index ;
AVStream * st ;
int discard ; /* true if stream data should be discarded */
int decoding_needed ; /* true if the packets must be decoded in 'raw_fifo' */
AVCodec * dec ;
2011-12-06 01:37:27 +01:00
AVFrame * decoded_frame ;
AVFrame * filtered_frame ;
2011-08-30 15:44:47 +02:00
int64_t start ; /* time when read started */
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 ;
AVDictionary * opts ;
2011-12-26 03:35:54 +01:00
/* a pool of free buffers for decoded data */
FrameBuffer * buffer_pool ;
2011-12-27 05:22:44 +01:00
int dr1 ;
2011-08-30 15:44:47 +02:00
} InputStream ;
typedef struct InputFile {
AVFormatContext * ctx ;
int eof_reached ; /* true if eof reached */
2011-10-11 14:24:20 +02:00
int ist_index ; /* index of first stream in input_streams */
2011-08-30 15:44:47 +02:00
int buffer_size ; /* current total buffer size */
int64_t ts_offset ;
2011-10-11 14:24:20 +02:00
int nb_streams ; /* number of stream that ffmpeg is aware of; may be different
2011-08-30 16:43:11 +02:00
from ctx . nb_streams if new streams appear during av_read_frame ( ) */
2011-09-05 22:10:26 +02:00
int rate_emu ;
2011-08-30 15:44:47 +02:00
} InputFile ;
2005-05-26 10:59:05 +02:00
2011-06-23 19:14:08 +02:00
typedef struct OutputStream {
2001-07-22 16:37:44 +02:00
int file_index ; /* file index */
int index ; /* stream index in the output file */
2011-06-23 19:14:08 +02:00
int source_index ; /* InputStream index */
2001-07-22 16:37:44 +02:00
AVStream * st ; /* stream in the output file */
2002-10-21 19:42:47 +02:00
int encoding_needed ; /* true if encoding needed for this stream */
int frame_number ;
/* input pts and corresponding output pts
for A / V sync */
2011-12-30 03:46:24 +01:00
// double sync_ipts; /* dts from the AVPacket of the demuxer in second units */
2011-06-23 19:14:08 +02:00
struct InputStream * sync_ist ; /* input stream to sync against */
2011-12-30 03:46:24 +01:00
int64_t sync_opts ; /* output frame counter, could be changed to some true timestamp */ // FIXME look at frame_number
2010-10-16 12:06:13 +02:00
AVBitStreamFilterContext * bitstream_filters ;
2011-06-16 18:04:56 +02:00
AVCodec * enc ;
2011-09-05 22:10:26 +02:00
int64_t max_frames ;
2011-06-16 18:04:56 +02:00
2001-07-22 16:37:44 +02:00
/* video only */
2006-04-10 11:04:15 +02:00
int video_resample ;
2011-05-06 11:30:27 +02:00
AVFrame resample_frame ; /* temporary frame for image resampling */
2006-08-02 13:50:38 +02:00
struct SwsContext * img_resample_ctx ; /* for image resampling */
int resample_height ;
2009-06-19 16:43:36 +02:00
int resample_width ;
2009-06-26 03:08:26 +02:00
int resample_pix_fmt ;
2011-06-15 08:00:03 +02:00
AVRational frame_rate ;
2011-09-11 23:35:35 +02:00
int force_fps ;
int top_field_first ;
2002-12-05 10:00:18 +01:00
2011-04-17 01:47:24 +02:00
float frame_aspect_ratio ;
2011-04-01 17:30:45 +02:00
2010-10-18 23:47:15 +02:00
/* forced key frames */
int64_t * forced_kf_pts ;
int forced_kf_count ;
int forced_kf_index ;
2001-07-22 16:37:44 +02:00
/* audio only */
int audio_resample ;
2011-11-04 18:54:01 +01:00
int audio_channels_map [ SWR_CH_MAX ] ; ///< list of the channels id to pick from the source stream
int audio_channels_mapped ; ///< number of channels in audio_channels_map
2010-12-12 17:18:50 +01:00
int resample_sample_fmt ;
int resample_channels ;
int resample_sample_rate ;
2011-10-26 00:45:52 +02:00
float rematrix_volume ;
2009-03-08 15:16:55 +01:00
AVFifoBuffer * fifo ; /* for compression: one audio fifo per codec */
2002-10-10 19:09:01 +02:00
FILE * logfile ;
2011-02-14 23:02:10 +01:00
2011-09-19 06:13:30 +02:00
struct SwrContext * swr ;
2011-02-14 23:02:10 +01:00
# if CONFIG_AVFILTER
AVFilterContext * output_video_filter ;
AVFilterContext * input_video_filter ;
AVFilterBufferRef * picref ;
char * avfilter ;
AVFilterGraph * graph ;
# endif
2011-05-10 04:01:29 +02:00
2011-11-07 02:41:01 +01:00
int64_t sws_flags ;
AVDictionary * opts ;
int is_past_recording_time ;
int stream_copy ;
const char * attachment_filename ;
int copy_initial_nonkeyframes ;
2011-06-23 19:14:08 +02:00
} OutputStream ;
2001-07-22 16:37:44 +02:00
2011-03-30 20:58:13 +02:00
# if HAVE_TERMIOS_H
/* init terminal so that we can grab keys */
static struct termios oldtty ;
# endif
2011-08-30 14:19:39 +02:00
typedef struct OutputFile {
AVFormatContext * ctx ;
AVDictionary * opts ;
2011-08-30 15:03:53 +02:00
int ost_index ; /* index of the first stream in output_streams */
2011-08-30 15:23:51 +02:00
int64_t recording_time ; /* desired length of the resulting file in microseconds */
2011-08-30 15:32:12 +02:00
int64_t start_time ; /* start time in microseconds */
2011-08-30 15:58:26 +02:00
uint64_t limit_filesize ;
2011-08-30 14:19:39 +02:00
} OutputFile ;
2011-12-30 03:46:24 +01:00
static InputStream * input_streams = NULL ;
2011-05-22 22:12:35 +02:00
static int nb_input_streams = 0 ;
2011-12-30 03:46:24 +01:00
static InputFile * input_files = NULL ;
2011-05-22 22:12:35 +02:00
static int nb_input_files = 0 ;
2011-08-30 15:03:53 +02:00
static OutputStream * output_streams = NULL ;
static int nb_output_streams = 0 ;
2011-08-30 14:19:39 +02:00
static OutputFile * output_files = NULL ;
static int nb_output_files = 0 ;
2011-09-05 02:04:27 +02:00
typedef struct OptionsContext {
/* input/output options */
int64_t start_time ;
const char * format ;
2011-09-05 22:10:26 +02:00
SpecifierOpt * codec_names ;
int nb_codec_names ;
2011-09-10 20:52:48 +02:00
SpecifierOpt * audio_channels ;
int nb_audio_channels ;
2011-09-11 23:35:35 +02:00
SpecifierOpt * audio_sample_rate ;
int nb_audio_sample_rate ;
2011-10-26 00:45:52 +02:00
SpecifierOpt * rematrix_volume ;
int nb_rematrix_volume ;
2011-09-11 23:35:35 +02:00
SpecifierOpt * frame_rates ;
int nb_frame_rates ;
SpecifierOpt * frame_sizes ;
int nb_frame_sizes ;
SpecifierOpt * frame_pix_fmts ;
int nb_frame_pix_fmts ;
2011-09-05 22:10:26 +02:00
2011-09-05 02:04:27 +02:00
/* input options */
int64_t input_ts_offset ;
2011-09-05 22:10:26 +02:00
int rate_emu ;
SpecifierOpt * ts_scale ;
int nb_ts_scale ;
2011-11-04 01:44:06 +01:00
SpecifierOpt * dump_attachment ;
int nb_dump_attachment ;
2011-09-05 02:04:27 +02:00
/* output options */
StreamMap * stream_maps ;
int nb_stream_maps ;
2011-11-04 18:54:01 +01:00
AudioChannelMap * audio_channel_maps ; ///< one info entry per -map_channel
int nb_audio_channel_maps ; ///< number of (valid) -map_channel settings
2011-09-05 22:10:26 +02:00
/* first item specifies output metadata, second is input */
MetadataMap ( * meta_data_maps ) [ 2 ] ;
int nb_meta_data_maps ;
int metadata_global_manual ;
int metadata_streams_manual ;
int metadata_chapters_manual ;
2011-11-04 01:44:06 +01:00
const char * * attachments ;
int nb_attachments ;
2011-09-05 22:10:26 +02:00
int chapters_input_file ;
2011-09-05 02:04:27 +02:00
int64_t recording_time ;
uint64_t limit_filesize ;
2011-09-05 22:10:26 +02:00
float mux_preload ;
float mux_max_delay ;
2011-09-10 20:52:48 +02:00
int video_disable ;
int audio_disable ;
int subtitle_disable ;
int data_disable ;
2011-09-11 23:35:35 +02:00
/* indexed by output file stream index */
int * streamid_map ;
int nb_streamid_map ;
2011-09-05 22:10:26 +02:00
SpecifierOpt * metadata ;
int nb_metadata ;
SpecifierOpt * max_frames ;
int nb_max_frames ;
SpecifierOpt * bitstream_filters ;
int nb_bitstream_filters ;
2011-09-10 20:52:48 +02:00
SpecifierOpt * codec_tags ;
int nb_codec_tags ;
2011-09-11 23:35:35 +02:00
SpecifierOpt * sample_fmts ;
int nb_sample_fmts ;
SpecifierOpt * qscale ;
int nb_qscale ;
SpecifierOpt * forced_key_frames ;
int nb_forced_key_frames ;
SpecifierOpt * force_fps ;
int nb_force_fps ;
SpecifierOpt * frame_aspect_ratios ;
int nb_frame_aspect_ratios ;
SpecifierOpt * rc_overrides ;
int nb_rc_overrides ;
SpecifierOpt * intra_matrices ;
int nb_intra_matrices ;
SpecifierOpt * inter_matrices ;
int nb_inter_matrices ;
SpecifierOpt * top_field_first ;
int nb_top_field_first ;
2011-12-17 01:36:59 +01:00
SpecifierOpt * metadata_map ;
int nb_metadata_map ;
2011-10-18 01:33:09 +02:00
SpecifierOpt * presets ;
int nb_presets ;
2011-11-07 02:41:01 +01:00
SpecifierOpt * copy_initial_nonkeyframes ;
int nb_copy_initial_nonkeyframes ;
2011-09-11 23:35:35 +02:00
# if CONFIG_AVFILTER
SpecifierOpt * filters ;
int nb_filters ;
# endif
2011-09-05 02:04:27 +02:00
} OptionsContext ;
2011-09-05 22:10:26 +02:00
# define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\
{ \
int i , ret ; \
for ( i = 0 ; i < o - > nb_ # # name ; i + + ) { \
char * spec = o - > name [ i ] . specifier ; \
if ( ( ret = check_stream_specifier ( fmtctx , st , spec ) ) > 0 ) \
outvar = o - > name [ i ] . u . type ; \
else if ( ret < 0 ) \
exit_program ( 1 ) ; \
} \
}
2011-09-05 03:11:18 +02:00
static void reset_options ( OptionsContext * o , int is_input )
2011-09-05 02:04:27 +02:00
{
const OptionDef * po = options ;
2011-09-05 03:11:18 +02:00
OptionsContext bak = * o ;
2011-09-05 02:04:27 +02:00
/* all OPT_SPEC and OPT_STRING can be freed in generic way */
while ( po - > name ) {
void * dst = ( uint8_t * ) o + po - > u . off ;
if ( po - > flags & OPT_SPEC ) {
SpecifierOpt * * so = dst ;
int i , * count = ( int * ) ( so + 1 ) ;
for ( i = 0 ; i < * count ; i + + ) {
av_freep ( & ( * so ) [ i ] . specifier ) ;
if ( po - > flags & OPT_STRING )
av_freep ( & ( * so ) [ i ] . u . str ) ;
}
av_freep ( so ) ;
* count = 0 ;
} else if ( po - > flags & OPT_OFFSET & & po - > flags & OPT_STRING )
av_freep ( dst ) ;
po + + ;
}
av_freep ( & o - > stream_maps ) ;
2011-11-04 18:54:01 +01:00
av_freep ( & o - > audio_channel_maps ) ;
2011-09-05 22:10:26 +02:00
av_freep ( & o - > meta_data_maps ) ;
2011-09-11 23:35:35 +02:00
av_freep ( & o - > streamid_map ) ;
2011-09-05 02:04:27 +02:00
memset ( o , 0 , sizeof ( * o ) ) ;
2011-09-05 03:11:18 +02:00
if ( is_input ) o - > recording_time = bak . recording_time ;
else o - > recording_time = INT64_MAX ;
2011-09-05 22:10:26 +02:00
o - > mux_max_delay = 0.7 ;
o - > limit_filesize = UINT64_MAX ;
o - > chapters_input_file = INT_MAX ;
2011-09-05 02:04:27 +02:00
uninit_opts ( ) ;
init_opts ( ) ;
}
2011-12-26 03:35:54 +01:00
static int alloc_buffer ( InputStream * ist , FrameBuffer * * pbuf )
{
AVCodecContext * s = ist - > st - > codec ;
FrameBuffer * buf = av_mallocz ( sizeof ( * buf ) ) ;
2011-12-26 04:14:50 +01:00
int ret , i ;
2011-12-26 03:35:54 +01:00
const int pixel_size = av_pix_fmt_descriptors [ s - > pix_fmt ] . comp [ 0 ] . step_minus1 + 1 ;
int h_chroma_shift , v_chroma_shift ;
int edge = 32 ; // XXX should be avcodec_get_edge_width(), but that fails on svq1
int w = s - > width , h = s - > height ;
if ( ! buf )
return AVERROR ( ENOMEM ) ;
if ( ! ( s - > flags & CODEC_FLAG_EMU_EDGE ) ) {
w + = 2 * edge ;
h + = 2 * edge ;
}
avcodec_align_dimensions ( s , & w , & h ) ;
if ( ( ret = av_image_alloc ( buf - > base , buf - > linesize , w , h ,
s - > pix_fmt , 32 ) ) < 0 ) {
av_freep ( & buf ) ;
return ret ;
}
/* XXX this shouldn't be needed, but some tests break without this line
* those decoders are buggy and need to be fixed .
* the following tests fail :
* bethsoft - vid , cdgraphics , ansi , aasc , fraps - v1 , qtrle - 1 bit
*/
memset ( buf - > base [ 0 ] , 128 , ret ) ;
avcodec_get_chroma_sub_sample ( s - > pix_fmt , & h_chroma_shift , & v_chroma_shift ) ;
2011-12-26 04:14:50 +01:00
for ( i = 0 ; i < FF_ARRAY_ELEMS ( buf - > data ) ; i + + ) {
2011-12-26 03:35:54 +01:00
const int h_shift = i = = 0 ? 0 : h_chroma_shift ;
const int v_shift = i = = 0 ? 0 : v_chroma_shift ;
if ( s - > flags & CODEC_FLAG_EMU_EDGE )
buf - > data [ i ] = buf - > base [ i ] ;
else
buf - > data [ i ] = buf - > base [ i ] +
FFALIGN ( ( buf - > linesize [ i ] * edge > > v_shift ) +
( pixel_size * edge > > h_shift ) , 32 ) ;
}
buf - > w = s - > width ;
buf - > h = s - > height ;
buf - > pix_fmt = s - > pix_fmt ;
buf - > ist = ist ;
* pbuf = buf ;
return 0 ;
}
static void free_buffer_pool ( InputStream * ist )
{
FrameBuffer * buf = ist - > buffer_pool ;
while ( buf ) {
ist - > buffer_pool = buf - > next ;
av_freep ( & buf - > base [ 0 ] ) ;
av_free ( buf ) ;
buf = ist - > buffer_pool ;
}
}
static void unref_buffer ( InputStream * ist , FrameBuffer * buf )
{
av_assert0 ( buf - > refcount ) ;
buf - > refcount - - ;
if ( ! buf - > refcount ) {
buf - > next = ist - > buffer_pool ;
ist - > buffer_pool = buf ;
}
}
static int codec_get_buffer ( AVCodecContext * s , AVFrame * frame )
{
InputStream * ist = s - > opaque ;
FrameBuffer * buf ;
int ret , i ;
if ( ! ist - > buffer_pool & & ( ret = alloc_buffer ( ist , & ist - > buffer_pool ) ) < 0 )
return ret ;
buf = ist - > buffer_pool ;
ist - > buffer_pool = buf - > next ;
buf - > next = NULL ;
if ( buf - > w ! = s - > width | | buf - > h ! = s - > height | | buf - > pix_fmt ! = s - > pix_fmt ) {
av_freep ( & buf - > base [ 0 ] ) ;
av_free ( buf ) ;
2011-12-27 05:22:44 +01:00
ist - > dr1 = 0 ;
2011-12-26 03:35:54 +01:00
if ( ( ret = alloc_buffer ( ist , & buf ) ) < 0 )
return ret ;
}
buf - > refcount + + ;
frame - > opaque = buf ;
frame - > type = FF_BUFFER_TYPE_USER ;
frame - > extended_data = frame - > data ;
frame - > pkt_pts = s - > pkt ? s - > pkt - > pts : AV_NOPTS_VALUE ;
for ( i = 0 ; i < FF_ARRAY_ELEMS ( buf - > data ) ; i + + ) {
frame - > base [ i ] = buf - > base [ i ] ; // XXX h264.c uses base though it shouldn't
frame - > data [ i ] = buf - > data [ i ] ;
frame - > linesize [ i ] = buf - > linesize [ i ] ;
}
return 0 ;
}
static void codec_release_buffer ( AVCodecContext * s , AVFrame * frame )
{
InputStream * ist = s - > opaque ;
FrameBuffer * buf = frame - > opaque ;
int i ;
2011-12-27 05:34:50 +01:00
if ( frame - > type ! = FF_BUFFER_TYPE_USER )
return avcodec_default_release_buffer ( s , frame ) ;
2011-12-26 03:35:54 +01:00
for ( i = 0 ; i < FF_ARRAY_ELEMS ( frame - > data ) ; i + + )
frame - > data [ i ] = NULL ;
unref_buffer ( ist , buf ) ;
}
static void filter_release_buffer ( AVFilterBuffer * fb )
{
FrameBuffer * buf = fb - > priv ;
av_free ( fb ) ;
unref_buffer ( buf - > ist , buf ) ;
}
2010-05-07 11:43:21 +02:00
# if CONFIG_AVFILTER
2011-06-23 19:14:08 +02:00
static int configure_video_filters ( InputStream * ist , OutputStream * ost )
2010-05-07 11:43:21 +02:00
{
2010-05-11 19:23:06 +02:00
AVFilterContext * last_filter , * filter ;
2010-05-07 11:43:21 +02:00
/** filter graph containing all filters including input & output */
AVCodecContext * codec = ost - > st - > codec ;
AVCodecContext * icodec = ist - > st - > codec ;
2011-06-11 18:43:11 +02:00
enum PixelFormat pix_fmts [ ] = { codec - > pix_fmt , PIX_FMT_NONE } ;
2011-08-18 16:21:47 +02:00
AVBufferSinkParams * buffersink_params = av_buffersink_params_alloc ( ) ;
2011-01-31 20:48:35 +01:00
AVRational sample_aspect_ratio ;
2010-05-07 11:43:21 +02:00
char args [ 255 ] ;
2010-08-24 17:48:11 +02:00
int ret ;
2010-05-07 11:43:21 +02:00
2011-02-14 23:02:10 +01:00
ost - > graph = avfilter_graph_alloc ( ) ;
2010-05-07 11:43:21 +02:00
2011-12-30 03:46:24 +01:00
if ( ist - > st - > sample_aspect_ratio . num ) {
2011-01-31 20:48:35 +01:00
sample_aspect_ratio = ist - > st - > sample_aspect_ratio ;
2011-12-30 03:46:24 +01:00
} else
2011-01-31 20:48:35 +01:00
sample_aspect_ratio = ist - > st - > codec - > sample_aspect_ratio ;
snprintf ( args , 255 , " %d:%d:%d:%d:%d:%d:%d " , ist - > st - > codec - > width ,
ist - > st - > codec - > height , ist - > st - > codec - > pix_fmt , 1 , AV_TIME_BASE ,
sample_aspect_ratio . num , sample_aspect_ratio . den ) ;
2011-02-14 23:02:10 +01:00
ret = avfilter_graph_create_filter ( & ost - > input_video_filter , avfilter_get_by_name ( " buffer " ) ,
" src " , args , NULL , ost - > graph ) ;
2010-12-02 21:12:27 +01:00
if ( ret < 0 )
2010-08-24 17:48:11 +02:00
return ret ;
2011-08-18 16:21:47 +02:00
# if FF_API_OLD_VSINK_API
2011-06-11 18:43:11 +02:00
ret = avfilter_graph_create_filter ( & ost - > output_video_filter , avfilter_get_by_name ( " buffersink " ) ,
" out " , NULL , pix_fmts , ost - > graph ) ;
2011-08-18 16:21:47 +02:00
# else
buffersink_params - > pixel_fmts = pix_fmts ;
ret = avfilter_graph_create_filter ( & ost - > output_video_filter , avfilter_get_by_name ( " buffersink " ) ,
" out " , NULL , buffersink_params , ost - > graph ) ;
# endif
av_freep ( & buffersink_params ) ;
2010-12-02 21:12:27 +01:00
if ( ret < 0 )
2010-08-24 17:48:11 +02:00
return ret ;
2011-02-14 23:02:10 +01:00
last_filter = ost - > input_video_filter ;
2010-05-07 11:43:21 +02:00
2011-12-30 03:46:24 +01:00
if ( codec - > width ! = icodec - > width | | codec - > height ! = icodec - > height ) {
2010-05-11 19:16:52 +02:00
snprintf ( args , 255 , " %d:%d:flags=0x%X " ,
2010-05-07 14:16:23 +02:00
codec - > width ,
codec - > height ,
2011-10-13 04:55:40 +02:00
( unsigned ) ost - > sws_flags ) ;
2010-12-02 21:12:27 +01:00
if ( ( ret = avfilter_graph_create_filter ( & filter , avfilter_get_by_name ( " scale " ) ,
2011-02-14 23:02:10 +01:00
NULL , args , NULL , ost - > graph ) ) < 0 )
2010-08-24 17:48:11 +02:00
return ret ;
if ( ( ret = avfilter_link ( last_filter , 0 , filter , 0 ) ) < 0 )
return ret ;
2010-05-11 19:23:06 +02:00
last_filter = filter ;
2010-05-07 11:43:21 +02:00
}
2011-10-13 04:55:40 +02:00
snprintf ( args , sizeof ( args ) , " flags=0x%X " , ( unsigned ) ost - > sws_flags ) ;
2011-02-14 23:02:10 +01:00
ost - > graph - > scale_sws_opts = av_strdup ( args ) ;
2010-07-03 05:11:04 +02:00
2011-02-14 23:02:10 +01:00
if ( ost - > avfilter ) {
2011-06-11 15:30:46 +02:00
AVFilterInOut * outputs = avfilter_inout_alloc ( ) ;
AVFilterInOut * inputs = avfilter_inout_alloc ( ) ;
2010-05-07 11:43:21 +02:00
outputs - > name = av_strdup ( " in " ) ;
2010-11-07 19:40:18 +01:00
outputs - > filter_ctx = last_filter ;
2010-05-07 11:43:21 +02:00
outputs - > pad_idx = 0 ;
outputs - > next = NULL ;
inputs - > name = av_strdup ( " out " ) ;
2011-02-14 23:02:10 +01:00
inputs - > filter_ctx = ost - > output_video_filter ;
2010-05-07 11:43:21 +02:00
inputs - > pad_idx = 0 ;
inputs - > next = NULL ;
2011-06-11 15:16:02 +02:00
if ( ( ret = avfilter_graph_parse ( ost - > graph , ost - > avfilter , & inputs , & outputs , NULL ) ) < 0 )
2010-08-24 17:48:11 +02:00
return ret ;
2011-02-14 23:02:10 +01:00
av_freep ( & ost - > avfilter ) ;
2010-05-07 11:43:21 +02:00
} else {
2011-02-14 23:02:10 +01:00
if ( ( ret = avfilter_link ( last_filter , 0 , ost - > output_video_filter , 0 ) ) < 0 )
2010-08-24 17:48:11 +02:00
return ret ;
2010-05-07 11:43:21 +02:00
}
2011-02-14 23:02:10 +01:00
if ( ( ret = avfilter_graph_config ( ost - > graph , NULL ) ) < 0 )
2010-08-24 17:48:11 +02:00
return ret ;
2010-05-07 11:43:21 +02:00
2011-02-14 23:02:10 +01:00
codec - > width = ost - > output_video_filter - > inputs [ 0 ] - > w ;
codec - > height = ost - > output_video_filter - > inputs [ 0 ] - > h ;
2011-01-31 20:48:35 +01:00
codec - > sample_aspect_ratio = ost - > st - > sample_aspect_ratio =
2011-08-30 15:57:16 +02:00
ost - > frame_aspect_ratio ? // overridden by the -aspect cli option
2011-12-30 03:46:24 +01:00
av_d2q ( ost - > frame_aspect_ratio * codec - > height / codec - > width , 255 ) :
2011-02-14 23:02:10 +01:00
ost - > output_video_filter - > inputs [ 0 ] - > sample_aspect_ratio ;
2010-05-07 11:43:21 +02:00
return 0 ;
}
# endif /* CONFIG_AVFILTER */
2001-07-22 16:37:44 +02:00
static void term_exit ( void )
{
2011-06-15 11:24:00 +02:00
av_log ( NULL , AV_LOG_QUIET , " %s " , " " ) ;
2011-03-30 20:58:13 +02:00
# if HAVE_TERMIOS_H
2011-04-22 18:49:44 +02:00
if ( ! run_as_daemon )
2011-04-18 13:10:52 +02:00
tcsetattr ( 0 , TCSANOW , & oldtty ) ;
2011-03-30 20:58:13 +02:00
# endif
2010-03-20 02:02:45 +01:00
}
2001-07-22 16:37:44 +02:00
2009-07-27 15:01:44 +02:00
static volatile int received_sigterm = 0 ;
2003-04-10 20:21:06 +02:00
2011-09-12 11:44:14 +02:00
static void sigterm_handler ( int sig )
2003-04-10 20:21:06 +02:00
{
received_sigterm = sig ;
2011-10-08 17:21:25 +02:00
received_nb_signals + + ;
2003-04-10 20:21:06 +02:00
term_exit ( ) ;
2011-12-16 19:37:32 +01:00
if ( received_nb_signals > 3 )
exit ( 123 ) ;
2003-04-10 20:21:06 +02:00
}
2001-07-22 16:37:44 +02:00
static void term_init ( void )
{
2011-03-30 20:58:13 +02:00
# if HAVE_TERMIOS_H
2011-04-22 18:49:44 +02:00
if ( ! run_as_daemon ) {
2011-03-30 20:58:13 +02:00
struct termios tty ;
tcgetattr ( 0 , & tty ) ;
oldtty = tty ;
atexit ( term_exit ) ;
tty . c_iflag & = ~ ( IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON ) ;
tty . c_oflag | = OPOST ;
tty . c_lflag & = ~ ( ECHO | ECHONL | ICANON | IEXTEN ) ;
tty . c_cflag & = ~ ( CSIZE | PARENB ) ;
tty . c_cflag | = CS8 ;
tty . c_cc [ VMIN ] = 1 ;
tty . c_cc [ VTIME ] = 0 ;
tcsetattr ( 0 , TCSANOW , & tty ) ;
signal ( SIGQUIT , sigterm_handler ) ; /* Quit (POSIX). */
2011-04-18 13:10:52 +02:00
}
2011-03-30 20:58:13 +02:00
# endif
2011-11-07 02:41:01 +01:00
avformat_network_deinit ( ) ;
2011-03-30 20:58:13 +02:00
2011-12-30 03:46:24 +01:00
signal ( SIGINT , sigterm_handler ) ; /* Interrupt (ANSI). */
2003-04-10 20:21:06 +02:00
signal ( SIGTERM , sigterm_handler ) ; /* Termination (ANSI). */
2010-01-20 07:42:39 +01:00
# ifdef SIGXCPU
signal ( SIGXCPU , sigterm_handler ) ;
# endif
2001-07-22 16:37:44 +02:00
}
/* read a key without blocking */
static int read_key ( void )
{
2011-09-04 00:24:06 +02:00
unsigned char ch ;
2011-03-30 20:58:13 +02:00
# if HAVE_TERMIOS_H
int n = 1 ;
struct timeval tv ;
fd_set rfds ;
FD_ZERO ( & rfds ) ;
FD_SET ( 0 , & rfds ) ;
tv . tv_sec = 0 ;
tv . tv_usec = 0 ;
n = select ( 1 , & rfds , NULL , NULL , & tv ) ;
if ( n > 0 ) {
n = read ( 0 , & ch , 1 ) ;
if ( n = = 1 )
return ch ;
return n ;
}
# elif HAVE_KBHIT
2011-09-04 00:24:06 +02:00
# if HAVE_PEEKNAMEDPIPE
static int is_pipe ;
static HANDLE input_handle ;
DWORD dw , nchars ;
if ( ! input_handle ) {
input_handle = GetStdHandle ( STD_INPUT_HANDLE ) ;
is_pipe = ! GetConsoleMode ( input_handle , & dw ) ;
}
if ( stdin - > _cnt > 0 ) {
read ( 0 , & ch , 1 ) ;
return ch ;
}
if ( is_pipe ) {
/* When running under a GUI, you will end here. */
if ( ! PeekNamedPipe ( input_handle , NULL , 0 , NULL , & nchars , NULL ) )
return - 1 ;
//Read it
if ( nchars ! = 0 ) {
read ( 0 , & ch , 1 ) ;
return ch ;
} else {
return - 1 ;
}
}
# endif
2007-07-11 16:07:55 +02:00
if ( kbhit ( ) )
return ( getch ( ) ) ;
2006-11-22 13:15:58 +01:00
# endif
2001-07-22 16:37:44 +02:00
return - 1 ;
}
2011-11-19 01:55:55 +01:00
static int decode_interrupt_cb ( void * ctx )
2004-03-14 20:40:43 +01:00
{
2011-10-08 17:21:25 +02:00
return received_nb_signals > 1 ;
2004-03-14 20:40:43 +01:00
}
2011-11-19 01:55:55 +01:00
static const AVIOInterruptCB int_cb = { decode_interrupt_cb , NULL } ;
2011-11-11 04:24:25 +01:00
void av_noreturn exit_program ( int ret )
2008-04-15 00:31:49 +02:00
{
int i ;
/* close files */
2011-12-30 03:46:24 +01:00
for ( i = 0 ; i < nb_output_files ; i + + ) {
2011-08-30 14:19:39 +02:00
AVFormatContext * s = output_files [ i ] . ctx ;
2008-04-21 03:22:25 +02:00
if ( ! ( s - > oformat - > flags & AVFMT_NOFILE ) & & s - > pb )
2011-02-21 22:45:20 +01:00
avio_close ( s - > pb ) ;
2011-02-04 11:04:18 +01:00
avformat_free_context ( s ) ;
2011-08-30 14:19:39 +02:00
av_dict_free ( & output_files [ i ] . opts ) ;
2008-04-15 00:31:49 +02:00
}
2012-01-02 02:48:34 +01:00
for ( i = 0 ; i < nb_output_streams ; i + + ) {
AVBitStreamFilterContext * bsfc = output_streams [ i ] . bitstream_filters ;
while ( bsfc ) {
AVBitStreamFilterContext * next = bsfc - > next ;
av_bitstream_filter_close ( bsfc ) ;
bsfc = next ;
}
output_streams [ i ] . bitstream_filters = NULL ;
2008-04-15 00:31:49 +02:00
}
2011-12-30 03:46:24 +01:00
for ( i = 0 ; i < nb_input_files ; i + + ) {
2011-12-13 00:29:25 +01:00
avformat_close_input ( & input_files [ i ] . ctx ) ;
2010-10-01 23:36:13 +02:00
}
2011-12-06 01:37:27 +01:00
for ( i = 0 ; i < nb_input_streams ; i + + ) {
av_freep ( & input_streams [ i ] . decoded_frame ) ;
av_freep ( & input_streams [ i ] . filtered_frame ) ;
2011-05-25 17:29:25 +02:00
av_dict_free ( & input_streams [ i ] . opts ) ;
2011-12-26 03:35:54 +01:00
free_buffer_pool ( & input_streams [ i ] ) ;
2011-12-06 01:37:27 +01:00
}
2008-04-15 00:31:49 +02:00
if ( vstats_file )
fclose ( vstats_file ) ;
av_free ( vstats_filename ) ;
2011-05-22 22:12:35 +02:00
av_freep ( & input_streams ) ;
av_freep ( & input_files ) ;
2011-08-30 15:03:53 +02:00
av_freep ( & output_streams ) ;
2011-08-30 14:19:39 +02:00
av_freep ( & output_files ) ;
2011-05-22 22:12:35 +02:00
2010-10-02 10:44:33 +02:00
uninit_opts ( ) ;
2009-04-13 05:55:26 +02:00
av_free ( audio_buf ) ;
av_free ( audio_out ) ;
2011-12-30 03:46:24 +01:00
allocated_audio_buf_size = allocated_audio_out_size = 0 ;
2009-04-13 05:47:12 +02:00
2010-05-07 11:43:21 +02:00
# if CONFIG_AVFILTER
avfilter_uninit ( ) ;
# endif
2011-11-06 01:47:48 +01:00
avformat_network_deinit ( ) ;
2010-05-07 11:43:21 +02:00
2011-09-02 00:16:19 +02:00
av_freep ( & input_tmp ) ;
2008-04-15 00:31:49 +02:00
if ( received_sigterm ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_INFO , " Received signal %d: terminating. \n " ,
( int ) received_sigterm ) ;
2008-04-15 00:31:49 +02:00
exit ( 255 ) ;
}
2008-04-15 00:35:32 +02:00
exit ( ret ) ; /* not all OS-es handle main() return value */
2010-10-01 23:29:37 +02:00
}
2011-06-09 10:58:23 +02:00
static void assert_avoptions ( AVDictionary * m )
{
AVDictionaryEntry * t ;
if ( ( t = av_dict_get ( m , " " , NULL , AV_DICT_IGNORE_SUFFIX ) ) ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Option %s not found. \n " , t - > key ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2011-06-09 10:58:23 +02:00
}
}
2011-07-12 17:18:42 +02:00
static void assert_codec_experimental ( AVCodecContext * c , int encoder )
{
const char * codec_string = encoder ? " encoder " : " decoder " ;
AVCodec * codec ;
if ( c - > codec - > capabilities & CODEC_CAP_EXPERIMENTAL & &
c - > strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " %s '%s' is experimental and might produce bad "
2011-07-12 17:18:42 +02:00
" results. \n Add '-strict experimental' if you want to use it. \n " ,
codec_string , c - > codec - > name ) ;
2011-07-14 22:01:29 +02:00
codec = encoder ? avcodec_find_encoder ( c - > codec - > id ) : avcodec_find_decoder ( c - > codec - > id ) ;
2011-07-12 17:18:42 +02:00
if ( ! ( codec - > capabilities & CODEC_CAP_EXPERIMENTAL ) )
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Or use the non experimental %s '%s'. \n " ,
2011-07-12 17:18:42 +02:00
codec_string , codec - > name ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2011-07-12 17:18:42 +02:00
}
}
2010-03-30 21:37:07 +02:00
static void choose_sample_fmt ( AVStream * st , AVCodec * codec )
{
2011-12-30 03:46:24 +01:00
if ( codec & & codec - > sample_fmts ) {
const enum AVSampleFormat * p = codec - > sample_fmts ;
for ( ; * p ! = - 1 ; p + + ) {
if ( * p = = st - > codec - > sample_fmt )
2010-03-30 21:37:07 +02:00
break ;
}
2011-01-14 15:50:55 +01:00
if ( * p = = - 1 ) {
2011-06-18 21:54:11 +02:00
if ( ( codec - > capabilities & CODEC_CAP_LOSSLESS ) & & av_get_sample_fmt_name ( st - > codec - > sample_fmt ) > av_get_sample_fmt_name ( codec - > sample_fmts [ 0 ] ) )
2011-11-05 11:30:16 +01:00
av_log ( NULL , AV_LOG_ERROR , " Conversion will not be lossless. \n " ) ;
2011-08-13 14:16:55 +02:00
if ( av_get_sample_fmt_name ( st - > codec - > sample_fmt ) )
2011-01-14 15:50:55 +01:00
av_log ( NULL , AV_LOG_WARNING ,
" Incompatible sample format '%s' for codec '%s', auto-selecting format '%s' \n " ,
av_get_sample_fmt_name ( st - > codec - > sample_fmt ) ,
codec - > name ,
av_get_sample_fmt_name ( codec - > sample_fmts [ 0 ] ) ) ;
2010-03-30 21:37:07 +02:00
st - > codec - > sample_fmt = codec - > sample_fmts [ 0 ] ;
2011-01-14 15:50:55 +01:00
}
2010-03-30 21:37:07 +02:00
}
}
2010-04-22 11:40:51 +02:00
static void choose_sample_rate ( AVStream * st , AVCodec * codec )
{
2011-12-30 03:46:24 +01:00
if ( codec & & codec - > supported_samplerates ) {
const int * p = codec - > supported_samplerates ;
int best = 0 ;
int best_dist = INT_MAX ;
for ( ; * p ; p + + ) {
int dist = abs ( st - > codec - > sample_rate - * p ) ;
if ( dist < best_dist ) {
best_dist = dist ;
best = * p ;
2010-04-22 11:40:51 +02:00
}
}
2011-12-30 03:46:24 +01:00
if ( best_dist ) {
2010-04-30 02:06:36 +02:00
av_log ( st - > codec , AV_LOG_WARNING , " Requested sampling rate unsupported using closest supported (%d) \n " , best ) ;
}
2011-12-30 03:46:24 +01:00
st - > codec - > sample_rate = best ;
2010-04-22 11:40:51 +02:00
}
}
2010-03-30 21:37:07 +02:00
static void choose_pixel_fmt ( AVStream * st , AVCodec * codec )
{
2011-12-30 03:46:24 +01:00
if ( codec & & codec - > pix_fmts ) {
const enum PixelFormat * p = codec - > pix_fmts ;
2011-12-04 15:26:52 +01:00
int has_alpha = av_pix_fmt_descriptors [ st - > codec - > pix_fmt ] . nb_components % 2 = = 0 ;
enum PixelFormat best = PIX_FMT_NONE ;
2011-12-30 03:46:24 +01:00
if ( st - > codec - > strict_std_compliance < = FF_COMPLIANCE_UNOFFICIAL ) {
if ( st - > codec - > codec_id = = CODEC_ID_MJPEG ) {
p = ( const enum PixelFormat [ ] ) { PIX_FMT_YUVJ420P , PIX_FMT_YUVJ422P , PIX_FMT_YUV420P , PIX_FMT_YUV422P , PIX_FMT_NONE } ;
} else if ( st - > codec - > codec_id = = CODEC_ID_LJPEG ) {
p = ( const enum PixelFormat [ ] ) { PIX_FMT_YUVJ420P , PIX_FMT_YUVJ422P , PIX_FMT_YUVJ444P , PIX_FMT_YUV420P ,
PIX_FMT_YUV422P , PIX_FMT_YUV444P , PIX_FMT_BGRA , PIX_FMT_NONE } ;
2011-01-05 05:52:32 +01:00
}
}
2011-11-23 04:02:17 +01:00
for ( ; * p ! = PIX_FMT_NONE ; p + + ) {
2011-12-04 15:26:52 +01:00
best = avcodec_find_best_pix_fmt2 ( best , * p , st - > codec - > pix_fmt , has_alpha , NULL ) ;
2011-12-30 03:46:24 +01:00
if ( * p = = st - > codec - > pix_fmt )
2010-03-30 21:37:07 +02:00
break ;
}
2011-11-23 04:02:17 +01:00
if ( * p = = PIX_FMT_NONE ) {
2011-12-30 03:46:24 +01:00
if ( st - > codec - > pix_fmt ! = PIX_FMT_NONE )
2011-03-26 15:26:45 +01:00
av_log ( NULL , AV_LOG_WARNING ,
2011-12-30 03:46:24 +01:00
" Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s' \n " ,
av_pix_fmt_descriptors [ st - > codec - > pix_fmt ] . name ,
codec - > name ,
av_pix_fmt_descriptors [ best ] . name ) ;
2011-12-04 15:26:52 +01:00
st - > codec - > pix_fmt = best ;
2011-03-26 15:26:45 +01:00
}
2010-03-30 21:37:07 +02:00
}
}
2011-09-12 11:44:14 +02:00
static double get_sync_ipts ( const OutputStream * ost )
2005-05-26 10:59:05 +02:00
{
2011-06-23 19:14:08 +02:00
const InputStream * ist = ost - > sync_ist ;
2011-08-30 15:32:12 +02:00
OutputFile * of = & output_files [ ost - > file_index ] ;
2011-12-30 03:46:24 +01:00
return ( double ) ( ist - > pts - of - > start_time ) / AV_TIME_BASE ;
2005-05-26 10:59:05 +02:00
}
2012-01-02 02:48:34 +01:00
static void write_frame ( AVFormatContext * s , AVPacket * pkt , OutputStream * ost )
2011-09-12 11:44:14 +02:00
{
2012-01-02 02:48:34 +01:00
AVBitStreamFilterContext * bsfc = ost - > bitstream_filters ;
AVCodecContext * avctx = ost - > st - > codec ;
2007-11-01 02:59:22 +01:00
int ret ;
2011-12-30 03:46:24 +01:00
while ( bsfc ) {
AVPacket new_pkt = * pkt ;
int a = av_bitstream_filter_filter ( bsfc , avctx , NULL ,
& new_pkt . data , & new_pkt . size ,
pkt - > data , pkt - > size ,
pkt - > flags & AV_PKT_FLAG_KEY ) ;
if ( a > 0 ) {
2006-07-06 17:04:46 +02:00
av_free_packet ( pkt ) ;
2011-12-30 03:46:24 +01:00
new_pkt . destruct = av_destruct_packet ;
} else if ( a < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_ERROR , " %s failed for stream %d, codec %s " ,
bsfc - > filter - > name , pkt - > stream_index ,
avctx - > codec ? avctx - > codec - > name : " copy " ) ;
2008-01-21 14:36:20 +01:00
print_error ( " " , a ) ;
2008-09-05 01:23:44 +02:00
if ( exit_on_error )
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2006-07-06 17:04:46 +02:00
}
2011-12-30 03:46:24 +01:00
* pkt = new_pkt ;
2006-07-06 17:04:46 +02:00
2011-12-30 03:46:24 +01:00
bsfc = bsfc - > next ;
2006-07-06 17:04:46 +02:00
}
2011-12-30 03:46:24 +01:00
ret = av_interleaved_write_frame ( s , pkt ) ;
if ( ret < 0 ) {
2007-11-01 02:59:22 +01:00
print_error ( " av_interleaved_write_frame() " , ret ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2007-11-01 02:59:22 +01:00
}
2012-01-02 02:48:34 +01:00
ost - > frame_number + + ;
2006-07-06 17:04:46 +02:00
}
2011-11-30 02:24:15 +01:00
static void generate_silence ( uint8_t * buf , enum AVSampleFormat sample_fmt , size_t size )
{
int fill_char = 0x00 ;
if ( sample_fmt = = AV_SAMPLE_FMT_U8 )
fill_char = 0x80 ;
memset ( buf , fill_char , size ) ;
}
2001-07-22 16:37:44 +02:00
2011-12-06 01:37:27 +01:00
static void do_audio_out ( AVFormatContext * s , OutputStream * ost ,
InputStream * ist , AVFrame * decoded_frame )
2001-07-22 16:37:44 +02:00
{
2003-02-11 17:35:48 +01:00
uint8_t * buftmp ;
2012-01-07 02:45:48 +01:00
int64_t audio_out_size , audio_buf_size , size_out ;
2003-03-20 02:32:17 +01:00
2012-01-07 02:45:48 +01:00
int frame_bytes , ret , resample_changed ;
2011-12-30 03:46:24 +01:00
AVCodecContext * enc = ost - > st - > codec ;
AVCodecContext * dec = ist - > st - > codec ;
2011-06-07 19:40:22 +02:00
int osize = av_get_bytes_per_sample ( enc - > sample_fmt ) ;
int isize = av_get_bytes_per_sample ( dec - > sample_fmt ) ;
2009-12-08 15:28:28 +01:00
const int coded_bps = av_get_bits_per_sample ( enc - > codec - > id ) ;
2011-12-06 01:37:27 +01:00
uint8_t * buf = decoded_frame - > data [ 0 ] ;
int size = decoded_frame - > nb_samples * dec - > channels * isize ;
int64_t allocated_for_size = size ;
2009-12-08 15:28:28 +01:00
2010-01-23 02:25:19 +01:00
need_realloc :
2011-12-30 03:46:24 +01:00
audio_buf_size = ( allocated_for_size + isize * dec - > channels - 1 ) / ( isize * dec - > channels ) ;
audio_buf_size = ( audio_buf_size * enc - > sample_rate + dec - > sample_rate ) / dec - > sample_rate ;
audio_buf_size = audio_buf_size * 2 + 10000 ; // safety factors for the deprecated resampling API
audio_buf_size = FFMAX ( audio_buf_size , enc - > frame_size ) ;
audio_buf_size * = osize * enc - > channels ;
audio_out_size = FFMAX ( audio_buf_size , enc - > frame_size * osize * enc - > channels ) ;
if ( coded_bps > 8 * osize )
audio_out_size = audio_out_size * coded_bps / ( 8 * osize ) ;
2009-12-08 15:28:28 +01:00
audio_out_size + = FF_MIN_BUFFER_SIZE ;
2011-12-30 03:46:24 +01:00
if ( audio_out_size > INT_MAX | | audio_buf_size > INT_MAX ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Buffer sizes too large \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2009-12-08 15:28:28 +01:00
}
2001-07-22 16:37:44 +02:00
2009-12-08 15:48:36 +01:00
av_fast_malloc ( & audio_buf , & allocated_audio_buf_size , audio_buf_size ) ;
av_fast_malloc ( & audio_out , & allocated_audio_out_size , audio_out_size ) ;
2011-12-30 03:46:24 +01:00
if ( ! audio_buf | | ! audio_out ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Out of memory in do_audio_out \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2009-12-08 15:50:46 +01:00
}
2003-03-20 02:32:17 +01:00
2011-09-19 06:13:30 +02:00
if ( enc - > channels ! = dec - > channels
2011-12-01 04:06:59 +01:00
| | enc - > sample_fmt ! = dec - > sample_fmt
| | enc - > sample_rate ! = dec - > sample_rate
)
2007-12-15 08:04:17 +01:00
ost - > audio_resample = 1 ;
2010-12-12 17:18:50 +01:00
resample_changed = ost - > resample_sample_fmt ! = dec - > sample_fmt | |
ost - > resample_channels ! = dec - > channels | |
ost - > resample_sample_rate ! = dec - > sample_rate ;
2011-11-04 18:54:01 +01:00
if ( ( ost - > audio_resample & & ! ost - > swr ) | | resample_changed | | ost - > audio_channels_mapped ) {
2010-12-12 17:18:50 +01:00
if ( resample_changed ) {
2011-11-07 02:41:01 +01:00
av_log ( NULL , AV_LOG_INFO , " Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d to rate:%d fmt:%s ch:%d \n " ,
2011-05-22 21:54:06 +02:00
ist - > file_index , ist - > st - > index ,
2010-12-12 17:18:50 +01:00
ost - > resample_sample_rate , av_get_sample_fmt_name ( ost - > resample_sample_fmt ) , ost - > resample_channels ,
dec - > sample_rate , av_get_sample_fmt_name ( dec - > sample_fmt ) , dec - > channels ) ;
ost - > resample_sample_fmt = dec - > sample_fmt ;
ost - > resample_channels = dec - > channels ;
ost - > resample_sample_rate = dec - > sample_rate ;
2011-09-19 06:13:30 +02:00
swr_free ( & ost - > swr ) ;
2010-12-12 17:18:50 +01:00
}
2011-01-23 02:06:59 +01:00
/* if audio_sync_method is >1 the resampler is needed for audio drift compensation */
2011-11-04 18:54:01 +01:00
if ( audio_sync_method < = 1 & & ! ost - > audio_channels_mapped & &
2011-01-23 02:06:59 +01:00
ost - > resample_sample_fmt = = enc - > sample_fmt & &
2010-12-12 17:18:50 +01:00
ost - > resample_channels = = enc - > channels & &
ost - > resample_sample_rate = = enc - > sample_rate ) {
2011-09-19 06:13:30 +02:00
//ost->swr = NULL;
2010-12-12 17:18:50 +01:00
ost - > audio_resample = 0 ;
} else {
2011-11-16 19:43:58 +01:00
ost - > swr = swr_alloc_set_opts ( ost - > swr ,
enc - > channel_layout , enc - > sample_fmt , enc - > sample_rate ,
dec - > channel_layout , dec - > sample_fmt , dec - > sample_rate ,
0 , NULL ) ;
2011-11-17 15:06:35 +01:00
if ( ost - > audio_channels_mapped )
swr_set_channel_mapping ( ost - > swr , ost - > audio_channels_map ) ;
2011-11-11 03:57:46 +01:00
av_opt_set_double ( ost - > swr , " rmvol " , ost - > rematrix_volume , 0 ) ;
2011-11-04 18:54:01 +01:00
if ( ost - > audio_channels_mapped ) {
2011-11-11 03:57:46 +01:00
av_opt_set_int ( ost - > swr , " icl " , av_get_default_channel_layout ( ost - > audio_channels_mapped ) , 0 ) ;
av_opt_set_int ( ost - > swr , " uch " , ost - > audio_channels_mapped , 0 ) ;
2011-11-04 18:54:01 +01:00
}
2012-01-06 02:02:50 +01:00
if ( av_opt_set_int ( ost - > swr , " ich " , dec - > channels , 0 ) < 0 ) {
av_log ( NULL , AV_LOG_FATAL , " Unsupported number of input channels \n " ) ;
exit_program ( 1 ) ;
}
if ( av_opt_set_int ( ost - > swr , " och " , enc - > channels , 0 ) < 0 ) {
av_log ( NULL , AV_LOG_FATAL , " Unsupported number of output channels \n " ) ;
exit_program ( 1 ) ;
}
2011-11-11 03:57:46 +01:00
if ( audio_sync_method > 1 ) av_opt_set_int ( ost - > swr , " flags " , SWR_FLAG_RESAMPLE , 0 ) ;
2011-09-19 06:13:30 +02:00
if ( ost - > swr & & swr_init ( ost - > swr ) < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " swr_init() failed \n " ) ;
2011-09-19 06:13:30 +02:00
swr_free ( & ost - > swr ) ;
}
if ( ! ost - > swr ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Can not resample %d channels @ %d Hz to %d channels @ %d Hz \n " ,
2010-12-12 17:19:40 +01:00
dec - > channels , dec - > sample_rate ,
enc - > channels , enc - > sample_rate ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2010-12-12 17:19:40 +01:00
}
2010-12-12 17:18:50 +01:00
}
2007-12-15 08:04:17 +01:00
}
2011-09-19 06:13:30 +02:00
av_assert0 ( ost - > audio_resample | | dec - > sample_fmt = = enc - > sample_fmt ) ;
2008-08-03 02:37:07 +02:00
2011-12-30 03:46:24 +01:00
if ( audio_sync_method ) {
double delta = get_sync_ipts ( ost ) * enc - > sample_rate - ost - > sync_opts -
av_fifo_size ( ost - > fifo ) / ( enc - > channels * osize ) ;
2011-11-30 02:24:15 +01:00
int idelta = delta * dec - > sample_rate / enc - > sample_rate ;
int byte_delta = idelta * isize * dec - > channels ;
2004-06-30 19:53:05 +02:00
2011-12-30 03:46:24 +01:00
// FIXME resample delay
if ( fabs ( delta ) > 50 ) {
if ( ist - > is_start | | fabs ( delta ) > audio_drift_threshold * enc - > sample_rate ) {
if ( byte_delta < 0 ) {
byte_delta = FFMAX ( byte_delta , - size ) ;
2004-06-30 19:53:05 +02:00
size + = byte_delta ;
buf - = byte_delta ;
2011-11-30 02:24:15 +01:00
av_log ( NULL , AV_LOG_VERBOSE , " discarding %d audio samples \n " ,
- byte_delta / ( isize * dec - > channels ) ) ;
2011-12-30 03:46:24 +01:00
if ( ! size )
2004-06-30 19:53:05 +02:00
return ;
2011-12-30 03:46:24 +01:00
ist - > is_start = 0 ;
} else {
input_tmp = av_realloc ( input_tmp , byte_delta + size ) ;
2004-06-30 19:53:05 +02:00
2011-12-30 03:46:24 +01:00
if ( byte_delta > allocated_for_size - size ) {
allocated_for_size = byte_delta + ( int64_t ) size ;
2010-01-23 02:25:19 +01:00
goto need_realloc ;
}
2011-12-30 03:46:24 +01:00
ist - > is_start = 0 ;
2004-06-30 19:53:05 +02:00
2011-11-30 02:24:15 +01:00
generate_silence ( input_tmp , dec - > sample_fmt , byte_delta ) ;
2004-06-30 19:53:05 +02:00
memcpy ( input_tmp + byte_delta , buf , size ) ;
2011-12-30 03:46:24 +01:00
buf = input_tmp ;
2004-06-30 19:53:05 +02:00
size + = byte_delta ;
2011-11-30 02:24:15 +01:00
av_log ( NULL , AV_LOG_VERBOSE , " adding %d audio samples of silence \n " , idelta ) ;
2004-06-30 19:53:05 +02:00
}
2011-12-30 03:46:24 +01:00
} else if ( audio_sync_method > 1 ) {
int comp = av_clip ( delta , - audio_sync_method , audio_sync_method ) ;
2010-09-30 23:57:31 +02:00
av_assert0 ( ost - > audio_resample ) ;
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_VERBOSE , " compensating audio timestamp drift:%f compensation:%d in:%d \n " ,
delta , comp , enc - > sample_rate ) ;
2009-03-08 15:16:55 +01:00
// fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2));
2011-09-19 06:13:30 +02:00
swr_compensate ( ost - > swr , comp , enc - > sample_rate ) ;
2004-06-30 19:53:05 +02:00
}
2005-12-17 19:14:38 +01:00
}
2011-12-30 03:46:24 +01:00
} else
ost - > sync_opts = lrintf ( get_sync_ipts ( ost ) * enc - > sample_rate ) -
av_fifo_size ( ost - > fifo ) / ( enc - > channels * osize ) ; // FIXME wrong
2001-07-22 16:37:44 +02:00
if ( ost - > audio_resample ) {
buftmp = audio_buf ;
2011-09-19 06:13:30 +02:00
size_out = swr_convert ( ost - > swr , ( uint8_t * [ ] ) { buftmp } , audio_buf_size / ( enc - > channels * osize ) ,
( const uint8_t * [ ] ) { buf } , size / ( dec - > channels * isize ) ) ;
2008-09-04 12:18:04 +02:00
size_out = size_out * enc - > channels * osize ;
2001-07-22 16:37:44 +02:00
} else {
buftmp = buf ;
size_out = size ;
}
2011-09-19 06:13:30 +02:00
av_assert0 ( ost - > audio_resample | | dec - > sample_fmt = = enc - > sample_fmt ) ;
2008-08-03 02:37:07 +02:00
2001-07-22 16:37:44 +02:00
/* now encode as many frames as possible */
2001-09-23 19:14:51 +02:00
if ( enc - > frame_size > 1 ) {
2001-07-22 16:37:44 +02:00
/* output resampled raw samples */
2009-03-08 15:16:55 +01:00
if ( av_fifo_realloc2 ( ost - > fifo , av_fifo_size ( ost - > fifo ) + size_out ) < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " av_fifo_realloc2() failed \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2008-08-19 20:49:57 +02:00
}
2009-03-08 15:16:55 +01:00
av_fifo_generic_write ( ost - > fifo , buftmp , size_out , NULL ) ;
2001-07-22 16:37:44 +02:00
2008-09-04 12:18:04 +02:00
frame_bytes = enc - > frame_size * osize * enc - > channels ;
2005-12-17 19:14:38 +01:00
2009-03-08 15:16:55 +01:00
while ( av_fifo_size ( ost - > fifo ) > = frame_bytes ) {
2004-05-29 04:06:32 +02:00
AVPacket pkt ;
av_init_packet ( & pkt ) ;
2009-03-09 18:47:47 +01:00
av_fifo_generic_read ( ost - > fifo , audio_buf , frame_bytes , NULL ) ;
2008-05-26 00:20:39 +02:00
2011-12-30 03:46:24 +01:00
// FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio()
2008-02-17 22:31:39 +01:00
2005-12-17 19:14:38 +01:00
ret = avcodec_encode_audio ( enc , audio_out , audio_out_size ,
2001-09-23 19:14:51 +02:00
( short * ) audio_buf ) ;
2009-01-11 17:15:34 +01:00
if ( ret < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Audio encoding failed \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2009-01-11 17:15:34 +01:00
}
2004-04-15 15:57:55 +02:00
audio_size + = ret ;
2011-12-30 03:46:24 +01:00
pkt . stream_index = ost - > index ;
pkt . data = audio_out ;
pkt . size = ret ;
if ( enc - > coded_frame & & enc - > coded_frame - > pts ! = AV_NOPTS_VALUE )
pkt . pts = av_rescale_q ( enc - > coded_frame - > pts , enc - > time_base , ost - > st - > time_base ) ;
2010-03-31 14:29:58 +02:00
pkt . flags | = AV_PKT_FLAG_KEY ;
2012-01-02 02:48:34 +01:00
write_frame ( s , & pkt , ost ) ;
2005-12-17 19:14:38 +01:00
2004-06-30 16:47:29 +02:00
ost - > sync_opts + = enc - > frame_size ;
2001-07-22 16:37:44 +02:00
}
} else {
2004-05-29 04:06:32 +02:00
AVPacket pkt ;
av_init_packet ( & pkt ) ;
2004-06-30 16:47:29 +02:00
2008-09-04 12:18:04 +02:00
ost - > sync_opts + = size_out / ( osize * enc - > channels ) ;
2004-06-30 16:47:29 +02:00
2001-09-23 19:14:51 +02:00
/* output a pcm frame */
2008-09-04 12:18:04 +02:00
/* determine the size of the coded buffer */
size_out / = osize ;
if ( coded_bps )
2011-12-30 03:46:24 +01:00
size_out = size_out * coded_bps / 8 ;
2008-09-04 12:18:04 +02:00
2011-12-30 03:46:24 +01:00
if ( size_out > audio_out_size ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Internal error, buffer size too small \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2009-12-08 15:18:15 +01:00
}
2011-12-30 03:46:24 +01:00
// FIXME pass ost->sync_opts as AVFrame.pts in avcodec_encode_audio()
2005-12-17 19:14:38 +01:00
ret = avcodec_encode_audio ( enc , audio_out , size_out ,
2005-12-22 02:10:11 +01:00
( short * ) buftmp ) ;
2009-01-11 17:15:34 +01:00
if ( ret < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Audio encoding failed \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2009-01-11 17:15:34 +01:00
}
2004-04-15 15:57:55 +02:00
audio_size + = ret ;
2011-12-30 03:46:24 +01:00
pkt . stream_index = ost - > index ;
pkt . data = audio_out ;
pkt . size = ret ;
if ( enc - > coded_frame & & enc - > coded_frame - > pts ! = AV_NOPTS_VALUE )
pkt . pts = av_rescale_q ( enc - > coded_frame - > pts , enc - > time_base , ost - > st - > time_base ) ;
2010-03-31 14:29:58 +02:00
pkt . flags | = AV_PKT_FLAG_KEY ;
2012-01-02 02:48:34 +01:00
write_frame ( s , & pkt , ost ) ;
2001-07-22 16:37:44 +02:00
}
}
2011-06-23 19:14:08 +02:00
static void pre_process_video_frame ( InputStream * ist , AVPicture * picture , void * * bufp )
2002-11-20 04:06:12 +01:00
{
AVCodecContext * dec ;
AVPicture * picture2 ;
AVPicture picture_tmp ;
2003-02-11 17:35:48 +01:00
uint8_t * buf = 0 ;
2002-11-20 04:06:12 +01:00
2005-07-18 00:24:36 +02:00
dec = ist - > st - > codec ;
2002-11-20 04:06:12 +01:00
/* deinterlace : must be done before any resize */
2009-03-03 15:09:10 +01:00
if ( do_deinterlace ) {
2002-11-20 04:06:12 +01:00
int size ;
/* create temporary picture */
size = avpicture_get_size ( dec - > pix_fmt , dec - > width , dec - > height ) ;
2011-12-30 03:46:24 +01:00
buf = av_malloc ( size ) ;
2002-11-20 04:06:12 +01:00
if ( ! buf )
return ;
2005-12-17 19:14:38 +01:00
2002-11-20 04:06:12 +01:00
picture2 = & picture_tmp ;
avpicture_fill ( picture2 , buf , dec - > pix_fmt , dec - > width , dec - > height ) ;
2011-12-30 03:46:24 +01:00
if ( avpicture_deinterlace ( picture2 , picture ,
2009-05-31 22:19:16 +02:00
dec - > pix_fmt , dec - > width , dec - > height ) < 0 ) {
/* if error, do not deinterlace */
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_WARNING , " Deinterlacing failed \n " ) ;
2009-05-31 22:19:16 +02:00
av_free ( buf ) ;
buf = NULL ;
picture2 = picture ;
}
2002-11-20 04:06:12 +01:00
} else {
picture2 = picture ;
}
if ( picture ! = picture2 )
* picture = * picture2 ;
* bufp = buf ;
}
2005-12-17 19:14:38 +01:00
static void do_subtitle_out ( AVFormatContext * s ,
2011-06-23 19:14:08 +02:00
OutputStream * ost ,
InputStream * ist ,
2005-06-03 16:31:45 +02:00
AVSubtitle * sub ,
int64_t pts )
{
static uint8_t * subtitle_out = NULL ;
2009-08-26 12:22:27 +02:00
int subtitle_out_max_size = 1024 * 1024 ;
2005-06-03 16:31:45 +02:00
int subtitle_out_size , nb , i ;
AVCodecContext * enc ;
AVPacket pkt ;
if ( pts = = AV_NOPTS_VALUE ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_ERROR , " Subtitle packets must have a pts \n " ) ;
2008-09-05 01:23:44 +02:00
if ( exit_on_error )
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2005-06-03 16:31:45 +02:00
return ;
}
2005-07-18 00:24:36 +02:00
enc = ost - > st - > codec ;
2005-06-03 16:31:45 +02:00
if ( ! subtitle_out ) {
subtitle_out = av_malloc ( subtitle_out_max_size ) ;
}
/* Note: DVB subtitle need one packet to draw them and one other
packet to clear them */
/* XXX: signal it in the codec context ? */
if ( enc - > codec_id = = CODEC_ID_DVB_SUBTITLE )
nb = 2 ;
else
nb = 1 ;
2011-12-30 03:46:24 +01:00
for ( i = 0 ; i < nb ; i + + ) {
2009-06-19 10:28:07 +02:00
sub - > pts = av_rescale_q ( pts , ist - > st - > time_base , AV_TIME_BASE_Q ) ;
2009-08-26 10:43:11 +02:00
// start_display_time is required to be 0
2011-12-30 03:46:24 +01:00
sub - > pts + = av_rescale_q ( sub - > start_display_time , ( AVRational ) { 1 , 1000 } , AV_TIME_BASE_Q ) ;
sub - > end_display_time - = sub - > start_display_time ;
2009-08-26 10:43:11 +02:00
sub - > start_display_time = 0 ;
2005-12-17 19:14:38 +01:00
subtitle_out_size = avcodec_encode_subtitle ( enc , subtitle_out ,
2005-06-03 16:31:45 +02:00
subtitle_out_max_size , sub ) ;
2009-08-15 02:37:31 +02:00
if ( subtitle_out_size < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Subtitle encoding failed \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2009-08-15 02:37:31 +02:00
}
2005-12-17 19:14:38 +01:00
2005-06-03 16:31:45 +02:00
av_init_packet ( & pkt ) ;
pkt . stream_index = ost - > index ;
pkt . data = subtitle_out ;
pkt . size = subtitle_out_size ;
2011-12-30 03:46:24 +01:00
pkt . pts = av_rescale_q ( sub - > pts , AV_TIME_BASE_Q , ost - > st - > time_base ) ;
2005-06-03 16:31:45 +02:00
if ( enc - > codec_id = = CODEC_ID_DVB_SUBTITLE ) {
/* XXX: the pts correction is handled here. Maybe handling
it in the codec would be better */
if ( i = = 0 )
pkt . pts + = 90 * sub - > start_display_time ;
else
pkt . pts + = 90 * sub - > end_display_time ;
}
2012-01-02 02:48:34 +01:00
write_frame ( s , & pkt , ost ) ;
2005-06-03 16:31:45 +02:00
}
}
2011-12-30 03:46:24 +01:00
static int bit_buffer_size = 1024 * 256 ;
static uint8_t * bit_buffer = NULL ;
2004-04-08 20:54:40 +02:00
2011-08-30 04:51:52 +02:00
static void do_video_resample ( OutputStream * ost ,
InputStream * ist ,
AVFrame * in_picture ,
AVFrame * * out_picture )
{
2011-09-01 02:27:38 +02:00
# if CONFIG_AVFILTER
2011-08-30 04:51:52 +02:00
* out_picture = in_picture ;
2011-09-01 02:27:38 +02:00
# else
2011-09-01 19:03:39 +02:00
AVCodecContext * dec = ist - > st - > codec ;
AVCodecContext * enc = ost - > st - > codec ;
2011-09-01 02:27:38 +02:00
int resample_changed = ost - > resample_width ! = dec - > width | |
ost - > resample_height ! = dec - > height | |
ost - > resample_pix_fmt ! = dec - > pix_fmt ;
2011-08-30 04:51:52 +02:00
2011-09-01 02:27:38 +02:00
* out_picture = in_picture ;
2011-08-30 04:51:52 +02:00
if ( resample_changed ) {
av_log ( NULL , AV_LOG_INFO ,
2011-11-07 02:41:01 +01:00
" Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s \n " ,
2011-08-30 04:51:52 +02:00
ist - > file_index , ist - > st - > index ,
ost - > resample_width , ost - > resample_height , av_get_pix_fmt_name ( ost - > resample_pix_fmt ) ,
dec - > width , dec - > height , av_get_pix_fmt_name ( dec - > pix_fmt ) ) ;
ost - > resample_width = dec - > width ;
ost - > resample_height = dec - > height ;
ost - > resample_pix_fmt = dec - > pix_fmt ;
}
ost - > video_resample = dec - > width ! = enc - > width | |
dec - > height ! = enc - > height | |
dec - > pix_fmt ! = enc - > pix_fmt ;
if ( ost - > video_resample ) {
* out_picture = & ost - > resample_frame ;
if ( ! ost - > img_resample_ctx | | resample_changed ) {
/* initialize the destination picture */
if ( ! ost - > resample_frame . data [ 0 ] ) {
avcodec_get_frame_defaults ( & ost - > resample_frame ) ;
if ( avpicture_alloc ( ( AVPicture * ) & ost - > resample_frame , enc - > pix_fmt ,
enc - > width , enc - > height ) ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Cannot allocate temp picture, check pix fmt \n " ) ;
2011-08-30 04:51:52 +02:00
exit_program ( 1 ) ;
}
}
/* initialize a new scaler context */
sws_freeContext ( ost - > img_resample_ctx ) ;
ost - > img_resample_ctx = sws_getContext ( dec - > width , dec - > height , dec - > pix_fmt ,
enc - > width , enc - > height , enc - > pix_fmt ,
ost - > sws_flags , NULL , NULL , NULL ) ;
if ( ost - > img_resample_ctx = = NULL ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Cannot get resampling context \n " ) ;
2011-08-30 04:51:52 +02:00
exit_program ( 1 ) ;
}
}
sws_scale ( ost - > img_resample_ctx , in_picture - > data , in_picture - > linesize ,
0 , ost - > resample_height , ( * out_picture ) - > data , ( * out_picture ) - > linesize ) ;
}
# endif
}
2005-12-17 19:14:38 +01:00
static void do_video_out ( AVFormatContext * s ,
2011-06-23 19:14:08 +02:00
OutputStream * ost ,
InputStream * ist ,
2003-12-12 17:56:38 +01:00
AVFrame * in_picture ,
2011-06-20 13:08:40 +02:00
int * frame_size , float quality )
2001-07-22 16:37:44 +02:00
{
2011-08-30 13:42:27 +02:00
int nb_frames , i , ret , format_video_sync ;
2011-08-30 04:51:52 +02:00
AVFrame * final_picture ;
2011-08-31 00:03:59 +02:00
AVCodecContext * enc ;
2010-03-15 03:32:21 +01:00
double sync_ipts ;
2011-09-13 05:13:34 +02:00
double duration = 0 ;
2005-12-17 19:14:38 +01:00
2005-07-18 00:24:36 +02:00
enc = ost - > st - > codec ;
2001-07-22 16:37:44 +02:00
2011-09-13 05:13:34 +02:00
if ( ist - > st - > start_time ! = AV_NOPTS_VALUE & & ist - > st - > first_dts ! = AV_NOPTS_VALUE ) {
duration = FFMAX ( av_q2d ( ist - > st - > time_base ) , av_q2d ( ist - > st - > codec - > time_base ) ) ;
if ( ist - > st - > avg_frame_rate . num )
duration = FFMAX ( duration , 1 / av_q2d ( ist - > st - > avg_frame_rate ) ) ;
duration / = av_q2d ( enc - > time_base ) ;
}
2010-03-15 03:32:21 +01:00
sync_ipts = get_sync_ipts ( ost ) / av_q2d ( enc - > time_base ) ;
2002-10-21 19:42:47 +02:00
/* by default, we output a single frame */
nb_frames = 1 ;
2003-01-17 05:14:50 +01:00
* frame_size = 0 ;
2011-08-30 13:42:27 +02:00
format_video_sync = video_sync_method ;
2012-01-05 02:03:12 +01:00
if ( format_video_sync = = VSYNC_AUTO )
format_video_sync = ( s - > oformat - > flags & AVFMT_VARIABLE_FPS ) ? ( ( s - > oformat - > flags & AVFMT_NOTIMESTAMPS ) ? VSYNC_PASSTHROUGH : VSYNC_VFR ) : 1 ;
2011-08-30 13:42:27 +02:00
2012-01-05 02:03:12 +01:00
if ( format_video_sync ! = VSYNC_PASSTHROUGH ) {
2011-09-13 05:13:34 +02:00
double vdelta = sync_ipts - ost - > sync_opts + duration ;
2011-12-30 03:46:24 +01:00
// FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
2004-05-29 04:06:32 +02:00
if ( vdelta < - 1.1 )
nb_frames = 0 ;
2012-01-05 02:03:12 +01:00
else if ( format_video_sync = = VSYNC_VFR ) {
2011-12-30 03:46:24 +01:00
if ( vdelta < = - 0.6 ) {
nb_frames = 0 ;
} else if ( vdelta > 0.6 )
ost - > sync_opts = lrintf ( sync_ipts ) ;
} else if ( vdelta > 1.1 )
2004-11-04 20:02:14 +01:00
nb_frames = lrintf ( vdelta ) ;
2009-02-27 15:44:58 +01:00
//fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, get_sync_ipts(ost), nb_frames);
2011-12-30 03:46:24 +01:00
if ( nb_frames = = 0 ) {
2004-06-15 15:49:12 +02:00
+ + nb_frames_drop ;
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_VERBOSE , " *** drop! \n " ) ;
2011-12-30 03:46:24 +01:00
} else if ( nb_frames > 1 ) {
2009-12-14 13:37:24 +01:00
nb_frames_dup + = nb_frames - 1 ;
2011-12-30 03:46:24 +01:00
av_log ( NULL , AV_LOG_VERBOSE , " *** %d dup! \n " , nb_frames - 1 ) ;
2004-06-15 15:49:12 +02:00
}
2011-12-30 03:46:24 +01:00
} else
ost - > sync_opts = lrintf ( sync_ipts ) ;
2003-07-12 09:37:05 +02:00
2011-09-05 22:10:26 +02:00
nb_frames = FFMIN ( nb_frames , ost - > max_frames - ost - > frame_number ) ;
2005-12-17 19:14:38 +01:00
if ( nb_frames < = 0 )
2001-07-22 16:37:44 +02:00
return ;
2002-03-19 07:30:41 +01:00
2011-08-30 04:51:52 +02:00
do_video_resample ( ost , ist , in_picture , & final_picture ) ;
2006-04-10 11:04:15 +02:00
2001-07-22 16:37:44 +02:00
/* duplicates frame if needed */
2011-12-30 03:46:24 +01:00
for ( i = 0 ; i < nb_frames ; i + + ) {
2004-05-29 04:06:32 +02:00
AVPacket pkt ;
av_init_packet ( & pkt ) ;
2011-12-30 03:46:24 +01:00
pkt . stream_index = ost - > index ;
2004-05-29 04:06:32 +02:00
2011-12-03 02:08:55 +01:00
if ( s - > oformat - > flags & AVFMT_RAWPICTURE & &
enc - > codec - > id = = CODEC_ID_RAWVIDEO ) {
2003-03-16 22:03:20 +01:00
/* raw pictures are written as AVPicture structure to
2011-08-30 15:57:16 +02:00
avoid any copies . We support temporarily the older
2003-03-16 22:03:20 +01:00
method . */
2011-08-31 00:03:59 +02:00
enc - > coded_frame - > interlaced_frame = in_picture - > interlaced_frame ;
enc - > coded_frame - > top_field_first = in_picture - > top_field_first ;
2011-12-30 03:46:24 +01:00
pkt . data = ( uint8_t * ) final_picture ;
pkt . size = sizeof ( AVPicture ) ;
pkt . pts = av_rescale_q ( ost - > sync_opts , enc - > time_base , ost - > st - > time_base ) ;
2010-03-31 14:29:58 +02:00
pkt . flags | = AV_PKT_FLAG_KEY ;
2004-05-29 04:06:32 +02:00
2012-01-02 02:48:34 +01:00
write_frame ( s , & pkt , ost ) ;
2003-03-16 22:03:20 +01:00
} else {
2002-12-09 13:03:43 +01:00
AVFrame big_picture ;
2004-04-17 21:41:49 +02:00
2011-12-30 03:46:24 +01:00
big_picture = * final_picture ;
2003-12-12 17:56:38 +01:00
/* better than nothing: use input picture interlaced
settings */
big_picture . interlaced_frame = in_picture - > interlaced_frame ;
2011-05-06 17:59:15 +02:00
if ( ost - > st - > codec - > flags & ( CODEC_FLAG_INTERLACED_DCT | CODEC_FLAG_INTERLACED_ME ) ) {
2011-09-11 23:35:35 +02:00
if ( ost - > top_field_first = = - 1 )
2003-12-30 17:07:57 +01:00
big_picture . top_field_first = in_picture - > top_field_first ;
else
2011-09-11 23:35:35 +02:00
big_picture . top_field_first = ! ! ost - > top_field_first ;
2003-12-30 17:07:57 +01:00
}
2003-12-12 17:56:38 +01:00
2011-08-30 01:46:34 +02:00
/* handles same_quant here. This is not correct because it may
2001-07-22 16:37:44 +02:00
not be a global option */
2011-06-20 13:08:40 +02:00
big_picture . quality = quality ;
2011-09-11 23:35:35 +02:00
if ( ! enc - > me_threshold )
2004-04-23 21:06:30 +02:00
big_picture . pict_type = 0 ;
2004-06-15 15:49:12 +02:00
// big_picture.pts = AV_NOPTS_VALUE;
2011-12-30 03:46:24 +01:00
big_picture . pts = ost - > sync_opts ;
2005-04-30 23:43:59 +02:00
// big_picture.pts= av_rescale(ost->sync_opts, AV_TIME_BASE*(int64_t)enc->time_base.num, enc->time_base.den);
2011-12-30 03:46:24 +01:00
// av_log(NULL, AV_LOG_DEBUG, "%"PRId64" -> encoder\n", ost->sync_opts);
2010-10-18 23:47:15 +02:00
if ( ost - > forced_kf_index < ost - > forced_kf_count & &
big_picture . pts > = ost - > forced_kf_pts [ ost - > forced_kf_index ] ) {
2011-04-28 01:40:44 +02:00
big_picture . pict_type = AV_PICTURE_TYPE_I ;
2010-10-18 23:47:15 +02:00
ost - > forced_kf_index + + ;
}
2005-12-17 19:14:38 +01:00
ret = avcodec_encode_video ( enc ,
2004-11-27 18:46:30 +01:00
bit_buffer , bit_buffer_size ,
2002-12-04 11:04:03 +01:00
& big_picture ) ;
2009-01-11 17:11:02 +01:00
if ( ret < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Video encoding failed \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2006-09-26 16:04:36 +02:00
}
2009-05-30 04:48:47 +02:00
2011-12-30 03:46:24 +01:00
if ( ret > 0 ) {
pkt . data = bit_buffer ;
pkt . size = ret ;
if ( enc - > coded_frame - > pts ! = AV_NOPTS_VALUE )
pkt . pts = av_rescale_q ( enc - > coded_frame - > pts , enc - > time_base , ost - > st - > time_base ) ;
2006-11-01 23:39:58 +01:00
/*av_log(NULL, AV_LOG_DEBUG, "encoder -> %"PRId64"/%"PRId64"\n",
2005-04-30 23:43:59 +02:00
pkt . pts ! = AV_NOPTS_VALUE ? av_rescale ( pkt . pts , enc - > time_base . den , AV_TIME_BASE * ( int64_t ) enc - > time_base . num ) : - 1 ,
pkt . dts ! = AV_NOPTS_VALUE ? av_rescale ( pkt . dts , enc - > time_base . den , AV_TIME_BASE * ( int64_t ) enc - > time_base . num ) : - 1 ) ; */
2004-06-15 15:49:12 +02:00
2011-12-30 03:46:24 +01:00
if ( enc - > coded_frame - > key_frame )
2010-03-31 14:29:58 +02:00
pkt . flags | = AV_PKT_FLAG_KEY ;
2012-01-02 02:48:34 +01:00
write_frame ( s , & pkt , ost ) ;
2004-05-29 04:06:32 +02:00
* frame_size = ret ;
2008-07-18 15:52:23 +02:00
video_size + = ret ;
2011-12-30 03:46:24 +01:00
// fprintf(stderr,"\nFrame: %3d size: %5d type: %d",
// enc->frame_number-1, ret, enc->pict_type);
2004-05-29 04:06:32 +02:00
/* if two pass, output log */
if ( ost - > logfile & & enc - > stats_out ) {
fprintf ( ost - > logfile , " %s " , enc - > stats_out ) ;
}
2002-10-10 19:09:01 +02:00
}
2001-07-22 16:37:44 +02:00
}
2004-06-15 15:49:12 +02:00
ost - > sync_opts + + ;
2001-07-22 16:37:44 +02:00
}
}
2011-09-12 11:44:14 +02:00
static double psnr ( double d )
{
2011-12-30 03:46:24 +01:00
return - 10.0 * log ( d ) / log ( 10.0 ) ;
2002-12-04 22:13:02 +01:00
}
2011-06-23 19:14:08 +02:00
static void do_video_stats ( AVFormatContext * os , OutputStream * ost ,
2002-10-21 19:42:47 +02:00
int frame_size )
2002-03-19 07:30:41 +01:00
{
AVCodecContext * enc ;
int frame_number ;
double ti1 , bitrate , avg_bitrate ;
2005-12-17 19:14:38 +01:00
2007-04-25 15:55:11 +02:00
/* this is executed just the first time do_video_stats is called */
2007-09-06 22:11:02 +02:00
if ( ! vstats_file ) {
vstats_file = fopen ( vstats_filename , " w " ) ;
if ( ! vstats_file ) {
2007-04-25 15:48:36 +02:00
perror ( " fopen " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2007-04-25 15:48:36 +02:00
}
}
2005-07-18 00:24:36 +02:00
enc = ost - > st - > codec ;
2010-03-31 01:30:55 +02:00
if ( enc - > codec_type = = AVMEDIA_TYPE_VIDEO ) {
2002-10-21 19:42:47 +02:00
frame_number = ost - > frame_number ;
2011-12-30 03:46:24 +01:00
fprintf ( vstats_file , " frame= %5d q= %2.1f " , frame_number , enc - > coded_frame - > quality / ( float ) FF_QP2LAMBDA ) ;
2002-12-04 22:13:02 +01:00
if ( enc - > flags & CODEC_FLAG_PSNR )
2011-12-30 03:46:24 +01:00
fprintf ( vstats_file , " PSNR= %6.2f " , psnr ( enc - > coded_frame - > error [ 0 ] / ( enc - > width * enc - > height * 255.0 * 255.0 ) ) ) ;
2005-12-17 19:14:38 +01:00
2007-09-06 22:11:02 +02:00
fprintf ( vstats_file , " f_size= %6d " , frame_size ) ;
2002-10-21 19:42:47 +02:00
/* compute pts value */
2005-04-30 23:43:59 +02:00
ti1 = ost - > sync_opts * av_q2d ( enc - > time_base ) ;
2002-03-19 07:30:41 +01:00
if ( ti1 < 0.01 )
ti1 = 0.01 ;
2005-12-17 19:14:38 +01:00
2011-12-30 03:46:24 +01:00
bitrate = ( frame_size * 8 ) / av_q2d ( enc - > time_base ) / 1000.0 ;
2004-04-15 15:57:55 +02:00
avg_bitrate = ( double ) ( video_size * 8 ) / ti1 / 1000.0 ;
2007-09-06 22:11:02 +02:00
fprintf ( vstats_file , " s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s " ,
2011-12-30 03:46:24 +01:00
( double ) video_size / 1024 , ti1 , bitrate , avg_bitrate ) ;
2011-04-29 16:37:23 +02:00
fprintf ( vstats_file , " type= %c \n " , av_get_picture_type_char ( enc - > coded_frame - > pict_type ) ) ;
2002-03-19 07:30:41 +01:00
}
2002-10-21 19:42:47 +02:00
}
2011-08-30 14:19:39 +02:00
static void print_report ( OutputFile * output_files ,
2011-08-30 15:03:53 +02:00
OutputStream * ost_table , int nb_ostreams ,
2011-10-08 17:32:06 +02:00
int is_last_report , int64_t timer_start , int64_t cur_time )
2002-10-21 19:42:47 +02:00
{
char buf [ 1024 ] ;
2011-06-23 19:14:08 +02:00
OutputStream * ost ;
2009-04-17 17:15:25 +02:00
AVFormatContext * oc ;
2003-02-11 17:35:48 +01:00
int64_t total_size ;
2002-10-21 19:42:47 +02:00
AVCodecContext * enc ;
int frame_number , vid , i ;
2011-06-03 00:28:52 +02:00
double bitrate ;
int64_t pts = INT64_MAX ;
2003-02-11 17:35:48 +01:00
static int64_t last_time = - 1 ;
2005-12-18 21:01:02 +01:00
static int qp_histogram [ 52 ] ;
2011-09-27 02:14:37 +02:00
int hours , mins , secs , us ;
2005-12-17 19:14:38 +01:00
2011-10-10 03:41:49 +02:00
if ( ! print_stats & & ! is_last_report )
return ;
2005-12-17 19:14:38 +01:00
2002-10-21 19:42:47 +02:00
if ( ! is_last_report ) {
if ( last_time = = - 1 ) {
last_time = cur_time ;
return ;
2005-12-17 19:14:38 +01:00
}
2002-10-21 19:42:47 +02:00
if ( ( cur_time - last_time ) < 500000 )
return ;
last_time = cur_time ;
}
2002-03-19 07:30:41 +01:00
2011-08-30 14:19:39 +02:00
oc = output_files [ 0 ] . ctx ;
2002-10-21 19:42:47 +02:00
2011-03-04 19:57:36 +01:00
total_size = avio_size ( oc - > pb ) ;
2011-11-29 17:59:40 +01:00
if ( total_size < 0 ) { // FIXME improve avio_size() so it works with non seekable output too
2011-12-30 03:46:24 +01:00
total_size = avio_tell ( oc - > pb ) ;
2011-11-29 17:59:40 +01:00
if ( total_size < 0 )
total_size = 0 ;
}
2005-12-17 19:14:38 +01:00
2002-10-21 19:42:47 +02:00
buf [ 0 ] = ' \0 ' ;
vid = 0 ;
2011-12-30 03:46:24 +01:00
for ( i = 0 ; i < nb_ostreams ; i + + ) {
2011-04-06 21:17:32 +02:00
float q = - 1 ;
2011-08-30 15:03:53 +02:00
ost = & ost_table [ i ] ;
2005-07-18 00:24:36 +02:00
enc = ost - > st - > codec ;
2011-10-26 02:09:31 +02:00
if ( ! ost - > stream_copy & & enc - > coded_frame )
2011-12-30 03:46:24 +01:00
q = enc - > coded_frame - > quality / ( float ) FF_QP2LAMBDA ;
2010-03-31 01:30:55 +02:00
if ( vid & & enc - > codec_type = = AVMEDIA_TYPE_VIDEO ) {
2011-04-06 21:17:32 +02:00
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " q=%2.1f " , q ) ;
2002-11-20 04:06:12 +01:00
}
2010-03-31 01:30:55 +02:00
if ( ! vid & & enc - > codec_type = = AVMEDIA_TYPE_VIDEO ) {
2011-10-08 17:32:06 +02:00
float t = ( cur_time - timer_start ) / 1000000.0 ;
2007-03-16 17:13:54 +01:00
2002-10-21 19:42:47 +02:00
frame_number = ost - > frame_number ;
2007-03-16 17:13:54 +01:00
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " frame=%5d fps=%3d q=%3.1f " ,
2011-12-30 03:46:24 +01:00
frame_number , ( t > 1 ) ? ( int ) ( frame_number / t + 0.5 ) : 0 , q ) ;
if ( is_last_report )
2005-01-12 01:16:25 +01:00
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " L " ) ;
2011-12-30 03:46:24 +01:00
if ( qp_hist ) {
2005-12-18 21:01:02 +01:00
int j ;
2011-04-06 21:17:32 +02:00
int qp = lrintf ( q ) ;
2011-12-30 03:46:24 +01:00
if ( qp > = 0 & & qp < FF_ARRAY_ELEMS ( qp_histogram ) )
2005-12-18 21:01:02 +01:00
qp_histogram [ qp ] + + ;
2011-12-30 03:46:24 +01:00
for ( j = 0 ; j < 32 ; j + + )
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " %X " , ( int ) lrintf ( log ( qp_histogram [ j ] + 1 ) / log ( 2 ) ) ) ;
2005-12-18 21:01:02 +01:00
}
2011-12-30 03:46:24 +01:00
if ( enc - > flags & CODEC_FLAG_PSNR ) {
2003-12-30 00:08:30 +01:00
int j ;
2011-12-30 03:46:24 +01:00
double error , error_sum = 0 ;
double scale , scale_sum = 0 ;
char type [ 3 ] = { ' Y ' , ' U ' , ' V ' } ;
2005-01-12 01:16:25 +01:00
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " PSNR= " ) ;
2011-12-30 03:46:24 +01:00
for ( j = 0 ; j < 3 ; j + + ) {
if ( is_last_report ) {
error = enc - > error [ j ] ;
scale = enc - > width * enc - > height * 255.0 * 255.0 * frame_number ;
} else {
error = enc - > coded_frame - > error [ j ] ;
scale = enc - > width * enc - > height * 255.0 * 255.0 ;
2003-12-30 00:08:30 +01:00
}
2011-12-30 03:46:24 +01:00
if ( j )
scale / = 4 ;
2003-12-30 00:08:30 +01:00
error_sum + = error ;
scale_sum + = scale ;
2011-12-30 03:46:24 +01:00
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " %c:%2.2f " , type [ j ] , psnr ( error / scale ) ) ;
2003-12-30 00:08:30 +01:00
}
2011-12-30 03:46:24 +01:00
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " *:%2.2f " , psnr ( error_sum / scale_sum ) ) ;
2003-12-30 00:08:30 +01:00
}
2002-10-21 19:42:47 +02:00
vid = 1 ;
}
/* compute min output value */
2011-06-03 00:28:52 +02:00
pts = FFMIN ( pts , av_rescale_q ( ost - > st - > pts . val ,
ost - > st - > time_base , AV_TIME_BASE_Q ) ) ;
2002-10-21 19:42:47 +02:00
}
2005-12-17 19:14:38 +01:00
2011-09-27 02:14:37 +02:00
secs = pts / AV_TIME_BASE ;
us = pts % AV_TIME_BASE ;
mins = secs / 60 ;
secs % = 60 ;
hours = mins / 60 ;
mins % = 60 ;
2005-12-17 19:14:38 +01:00
2011-09-27 02:14:37 +02:00
bitrate = pts ? total_size * 8 / ( pts / 1000.0 ) : 0 ;
2004-06-12 00:03:16 +02:00
2011-09-27 02:14:37 +02:00
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) ,
" size=%8.0fkB time= " , total_size / 1024.0 ) ;
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) ,
" %02d:%02d:%02d.%02d " , hours , mins , secs ,
( 100 * us ) / AV_TIME_BASE ) ;
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) ,
" bitrate=%6.1fkbits/s " , bitrate ) ;
2005-12-17 19:14:38 +01:00
2011-09-27 02:14:37 +02:00
if ( nb_frames_dup | | nb_frames_drop )
snprintf ( buf + strlen ( buf ) , sizeof ( buf ) - strlen ( buf ) , " dup=%d drop=%d " ,
nb_frames_dup , nb_frames_drop ) ;
2005-12-17 19:14:38 +01:00
2011-10-10 03:41:49 +02:00
av_log ( NULL , AV_LOG_INFO , " %s \r " , buf ) ;
2011-09-27 02:14:37 +02:00
fflush ( stderr ) ;
2005-12-17 19:14:38 +01:00
2011-09-27 02:14:37 +02:00
if ( is_last_report ) {
2004-04-15 15:57:55 +02:00
int64_t raw = audio_size + video_size + extra_size ;
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_INFO , " \n " ) ;
av_log ( NULL , AV_LOG_INFO , " video:%1.0fkB audio:%1.0fkB global headers:%1.0fkB muxing overhead %f%% \n " ,
2011-12-30 03:46:24 +01:00
video_size / 1024.0 ,
audio_size / 1024.0 ,
extra_size / 1024.0 ,
100.0 * ( total_size - raw ) / raw
2004-04-15 15:57:55 +02:00
) ;
2011-11-25 16:17:06 +01:00
if ( video_size + audio_size + extra_size = = 0 ) {
av_log ( NULL , AV_LOG_WARNING , " Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used) \n " ) ;
}
2004-04-15 15:57:55 +02:00
}
2002-03-19 07:30:41 +01:00
}
2011-08-30 16:00:47 +02:00
static void flush_encoders ( OutputStream * ost_table , int nb_ostreams )
2011-08-30 15:55:25 +02:00
{
int i , ret ;
for ( i = 0 ; i < nb_ostreams ; i + + ) {
2011-08-30 15:56:03 +02:00
OutputStream * ost = & ost_table [ i ] ;
AVCodecContext * enc = ost - > st - > codec ;
AVFormatContext * os = output_files [ ost - > file_index ] . ctx ;
2011-08-30 16:00:47 +02:00
if ( ! ost - > encoding_needed )
2011-08-30 15:56:03 +02:00
continue ;
2011-12-30 03:46:24 +01:00
if ( ost - > st - > codec - > codec_type = = AVMEDIA_TYPE_AUDIO & & enc - > frame_size < = 1 )
2011-08-30 15:56:03 +02:00
continue ;
2011-12-03 02:08:55 +01:00
if ( ost - > st - > codec - > codec_type = = AVMEDIA_TYPE_VIDEO & & ( os - > oformat - > flags & AVFMT_RAWPICTURE ) & & enc - > codec - > id = = CODEC_ID_RAWVIDEO )
2011-08-30 15:56:03 +02:00
continue ;
2011-12-30 03:46:24 +01:00
for ( ; ; ) {
2011-08-30 15:56:03 +02:00
AVPacket pkt ;
int fifo_bytes ;
av_init_packet ( & pkt ) ;
2011-12-30 03:46:24 +01:00
pkt . stream_index = ost - > index ;
2011-08-30 15:56:03 +02:00
switch ( ost - > st - > codec - > codec_type ) {
case AVMEDIA_TYPE_AUDIO :
fifo_bytes = av_fifo_size ( ost - > fifo ) ;
ret = 0 ;
/* encode any samples remaining in fifo */
if ( fifo_bytes > 0 ) {
int osize = av_get_bytes_per_sample ( enc - > sample_fmt ) ;
int fs_tmp = enc - > frame_size ;
av_fifo_generic_read ( ost - > fifo , audio_buf , fifo_bytes , NULL ) ;
if ( enc - > codec - > capabilities & CODEC_CAP_SMALL_LAST_FRAME ) {
enc - > frame_size = fifo_bytes / ( osize * enc - > channels ) ;
} else { /* pad */
int frame_bytes = enc - > frame_size * osize * enc - > channels ;
if ( allocated_audio_buf_size < frame_bytes )
2011-08-30 15:55:25 +02:00
exit_program ( 1 ) ;
2011-08-30 15:56:03 +02:00
generate_silence ( audio_buf + fifo_bytes , enc - > sample_fmt , frame_bytes - fifo_bytes ) ;
2011-08-30 15:55:25 +02:00
}
2011-08-30 15:56:03 +02:00
ret = avcodec_encode_audio ( enc , bit_buffer , bit_buffer_size , ( short * ) audio_buf ) ;
pkt . duration = av_rescale ( ( int64_t ) enc - > frame_size * ost - > st - > time_base . den ,
ost - > st - > time_base . num , enc - > sample_rate ) ;
enc - > frame_size = fs_tmp ;
}
if ( ret < = 0 ) {
ret = avcodec_encode_audio ( enc , bit_buffer , bit_buffer_size , NULL ) ;
2011-08-30 15:55:25 +02:00
}
2011-08-30 15:56:03 +02:00
if ( ret < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Audio encoding failed \n " ) ;
2011-08-30 15:56:03 +02:00
exit_program ( 1 ) ;
}
audio_size + = ret ;
2011-12-30 03:46:24 +01:00
pkt . flags | = AV_PKT_FLAG_KEY ;
2011-08-30 15:56:03 +02:00
break ;
case AVMEDIA_TYPE_VIDEO :
ret = avcodec_encode_video ( enc , bit_buffer , bit_buffer_size , NULL ) ;
if ( ret < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Video encoding failed \n " ) ;
2011-08-30 15:56:03 +02:00
exit_program ( 1 ) ;
}
video_size + = ret ;
2011-12-30 03:46:24 +01:00
if ( enc - > coded_frame & & enc - > coded_frame - > key_frame )
2011-08-30 15:56:03 +02:00
pkt . flags | = AV_PKT_FLAG_KEY ;
if ( ost - > logfile & & enc - > stats_out ) {
fprintf ( ost - > logfile , " %s " , enc - > stats_out ) ;
}
break ;
default :
2011-12-30 03:46:24 +01:00
ret = - 1 ;
2011-08-30 15:55:25 +02:00
}
2011-08-30 15:56:03 +02:00
if ( ret < = 0 )
break ;
pkt . data = bit_buffer ;
pkt . size = ret ;
if ( enc - > coded_frame & & enc - > coded_frame - > pts ! = AV_NOPTS_VALUE )
2011-12-30 03:46:24 +01:00
pkt . pts = av_rescale_q ( enc - > coded_frame - > pts , enc - > time_base , ost - > st - > time_base ) ;
2012-01-02 02:48:34 +01:00
write_frame ( os , & pkt , ost ) ;
2011-08-30 15:55:25 +02:00
}
}
}
2011-11-23 04:02:17 +01:00
/*
* Check whether a packet from ist should be written into ost at this time
*/
static int check_output_constraints ( InputStream * ist , OutputStream * ost )
{
OutputFile * of = & output_files [ ost - > file_index ] ;
int ist_index = ist - input_streams ;
if ( ost - > source_index ! = ist_index )
return 0 ;
if ( of - > start_time & & ist - > pts < of - > start_time )
return 0 ;
if ( of - > recording_time ! = INT64_MAX & &
av_compare_ts ( ist - > pts , AV_TIME_BASE_Q , of - > recording_time + of - > start_time ,
2011-12-30 03:46:24 +01:00
( AVRational ) { 1 , 1000000 } ) > = 0 ) {
2011-11-23 04:02:17 +01:00
ost - > is_past_recording_time = 1 ;
return 0 ;
}
return 1 ;
}
static void do_streamcopy ( InputStream * ist , OutputStream * ost , const AVPacket * pkt )
{
OutputFile * of = & output_files [ ost - > file_index ] ;
int64_t ost_tb_start_time = av_rescale_q ( of - > start_time , AV_TIME_BASE_Q , ost - > st - > time_base ) ;
AVPicture pict ;
AVPacket opkt ;
av_init_packet ( & opkt ) ;
if ( ( ! ost - > frame_number & & ! ( pkt - > flags & AV_PKT_FLAG_KEY ) ) & &
! ost - > copy_initial_nonkeyframes )
return ;
/* force the input stream PTS */
if ( ost - > st - > codec - > codec_type = = AVMEDIA_TYPE_AUDIO )
audio_size + = pkt - > size ;
else if ( ost - > st - > codec - > codec_type = = AVMEDIA_TYPE_VIDEO ) {
video_size + = pkt - > size ;
ost - > sync_opts + + ;
}
opkt . stream_index = ost - > index ;
if ( pkt - > pts ! = AV_NOPTS_VALUE )
opkt . pts = av_rescale_q ( pkt - > pts , ist - > st - > time_base , ost - > st - > time_base ) - ost_tb_start_time ;
else
opkt . pts = AV_NOPTS_VALUE ;
if ( pkt - > dts = = AV_NOPTS_VALUE )
opkt . dts = av_rescale_q ( ist - > pts , AV_TIME_BASE_Q , ost - > st - > time_base ) ;
else
opkt . dts = av_rescale_q ( pkt - > dts , ist - > st - > time_base , ost - > st - > time_base ) ;
opkt . dts - = ost_tb_start_time ;
opkt . duration = av_rescale_q ( pkt - > duration , ist - > st - > time_base , ost - > st - > time_base ) ;
opkt . flags = pkt - > flags ;
2011-12-30 03:46:24 +01:00
// FIXME remove the following 2 lines they shall be replaced by the bitstream filters
if ( ost - > st - > codec - > codec_id ! = CODEC_ID_H264
2011-11-23 04:02:17 +01:00
& & ost - > st - > codec - > codec_id ! = CODEC_ID_MPEG1VIDEO
& & ost - > st - > codec - > codec_id ! = CODEC_ID_MPEG2VIDEO
) {
if ( av_parser_change ( ist - > st - > parser , ost - > st - > codec , & opkt . data , & opkt . size , pkt - > data , pkt - > size , pkt - > flags & AV_PKT_FLAG_KEY ) )
opkt . destruct = av_destruct_packet ;
} else {
opkt . data = pkt - > data ;
opkt . size = pkt - > size ;
}
if ( of - > ctx - > oformat - > flags & AVFMT_RAWPICTURE ) {
/* store AVPicture in AVPacket, as expected by the output format */
avpicture_fill ( & pict , opkt . data , ost - > st - > codec - > pix_fmt , ost - > st - > codec - > width , ost - > st - > codec - > height ) ;
opkt . data = ( uint8_t * ) & pict ;
opkt . size = sizeof ( AVPicture ) ;
opkt . flags | = AV_PKT_FLAG_KEY ;
}
2012-01-02 02:48:34 +01:00
write_frame ( of - > ctx , & opkt , ost ) ;
2011-11-23 04:02:17 +01:00
ost - > st - > codec - > frame_number + + ;
av_free_packet ( & opkt ) ;
}
static void rate_emu_sleep ( InputStream * ist )
{
if ( input_files [ ist - > file_index ] . rate_emu ) {
int64_t pts = av_rescale ( ist - > pts , 1000000 , AV_TIME_BASE ) ;
int64_t now = av_gettime ( ) - ist - > start ;
if ( pts > now )
usleep ( pts - now ) ;
}
}
static int transcode_audio ( InputStream * ist , AVPacket * pkt , int * got_output )
{
2011-12-06 01:37:27 +01:00
AVFrame * decoded_frame ;
AVCodecContext * avctx = ist - > st - > codec ;
2011-11-23 04:02:17 +01:00
int bps = av_get_bytes_per_sample ( ist - > st - > codec - > sample_fmt ) ;
int i , ret ;
2011-12-06 01:37:27 +01:00
if ( ! ist - > decoded_frame & & ! ( ist - > decoded_frame = avcodec_alloc_frame ( ) ) )
return AVERROR ( ENOMEM ) ;
else
avcodec_get_frame_defaults ( ist - > decoded_frame ) ;
decoded_frame = ist - > decoded_frame ;
2011-11-23 04:02:17 +01:00
2011-12-06 01:37:27 +01:00
ret = avcodec_decode_audio4 ( avctx , decoded_frame , got_output , pkt ) ;
if ( ret < 0 ) {
2011-11-23 04:02:17 +01:00
return ret ;
2011-12-06 01:37:27 +01:00
}
2011-11-23 04:02:17 +01:00
if ( ! * got_output ) {
/* no audio frame */
2011-11-24 02:08:21 +01:00
return ret ;
2011-11-23 04:02:17 +01:00
}
2011-12-06 01:37:27 +01:00
/* if the decoder provides a pts, use it instead of the last packet pts.
the decoder could be delaying output by a packet or more . */
if ( decoded_frame - > pts ! = AV_NOPTS_VALUE )
ist - > next_pts = decoded_frame - > pts ;
/* increment next_pts to use for the case where the input stream does not
have timestamps or there are multiple frames in the packet */
ist - > next_pts + = ( ( int64_t ) AV_TIME_BASE * decoded_frame - > nb_samples ) /
avctx - > sample_rate ;
2011-11-23 04:02:17 +01:00
// preprocess audio (volume)
if ( audio_volume ! = 256 ) {
2011-12-06 01:37:27 +01:00
int decoded_data_size = decoded_frame - > nb_samples * avctx - > channels * bps ;
void * samples = decoded_frame - > data [ 0 ] ;
switch ( avctx - > sample_fmt ) {
2011-11-23 04:02:17 +01:00
case AV_SAMPLE_FMT_U8 :
{
uint8_t * volp = samples ;
for ( i = 0 ; i < ( decoded_data_size / sizeof ( * volp ) ) ; i + + ) {
int v = ( ( ( * volp - 128 ) * audio_volume + 128 ) > > 8 ) + 128 ;
* volp + + = av_clip_uint8 ( v ) ;
2011-02-14 23:02:10 +01:00
}
2011-11-23 04:02:17 +01:00
break ;
2010-05-07 11:43:21 +02:00
}
2011-11-23 04:02:17 +01:00
case AV_SAMPLE_FMT_S16 :
{
int16_t * volp = samples ;
for ( i = 0 ; i < ( decoded_data_size / sizeof ( * volp ) ) ; i + + ) {
int v = ( ( * volp ) * audio_volume + 128 ) > > 8 ;
* volp + + = av_clip_int16 ( v ) ;
2005-03-23 02:59:17 +01:00
}
2011-11-23 04:02:17 +01:00
break ;
2007-03-12 15:35:36 +01:00
}
2011-11-23 04:02:17 +01:00
case AV_SAMPLE_FMT_S32 :
{
int32_t * volp = samples ;
for ( i = 0 ; i < ( decoded_data_size / sizeof ( * volp ) ) ; i + + ) {
int64_t v = ( ( ( int64_t ) * volp * audio_volume + 128 ) > > 8 ) ;
* volp + + = av_clipl_int32 ( v ) ;
}
break ;
2007-03-12 15:35:36 +01:00
}
2011-11-23 04:02:17 +01:00
case AV_SAMPLE_FMT_FLT :
{
float * volp = samples ;
float scale = audio_volume / 256.f ;
for ( i = 0 ; i < ( decoded_data_size / sizeof ( * volp ) ) ; i + + ) {
* volp + + * = scale ;
}
break ;
}
case AV_SAMPLE_FMT_DBL :
{
double * volp = samples ;
double scale = audio_volume / 256. ;
for ( i = 0 ; i < ( decoded_data_size / sizeof ( * volp ) ) ; i + + ) {
* volp + + * = scale ;
}
break ;
}
default :
av_log ( NULL , AV_LOG_FATAL ,
" Audio volume adjustment on sample format %s is not supported. \n " ,
av_get_sample_fmt_name ( ist - > st - > codec - > sample_fmt ) ) ;
exit_program ( 1 ) ;
}
}
rate_emu_sleep ( ist ) ;
for ( i = 0 ; i < nb_output_streams ; i + + ) {
OutputStream * ost = & output_streams [ i ] ;
if ( ! check_output_constraints ( ist , ost ) | | ! ost - > encoding_needed )
continue ;
2011-12-06 01:37:27 +01:00
do_audio_out ( output_files [ ost - > file_index ] . ctx , ost , ist , decoded_frame ) ;
2011-11-23 04:02:17 +01:00
}
2011-12-06 01:37:27 +01:00
2011-11-24 02:08:21 +01:00
return ret ;
2011-11-23 04:02:17 +01:00
}
static int transcode_video ( InputStream * ist , AVPacket * pkt , int * got_output , int64_t * pkt_pts , int64_t * pkt_dts )
{
AVFrame * decoded_frame , * filtered_frame = NULL ;
void * buffer_to_free = NULL ;
int i , ret = 0 ;
float quality = 0 ;
2010-05-07 11:43:21 +02:00
# if CONFIG_AVFILTER
2011-11-23 04:02:17 +01:00
int frame_available = 1 ;
2010-05-07 11:43:21 +02:00
# endif
2011-12-01 03:12:39 +01:00
int duration = 0 ;
2011-12-03 21:20:50 +01:00
int64_t * best_effort_timestamp ;
AVRational * frame_sample_aspect ;
2009-04-09 02:13:59 +02:00
2011-12-06 01:37:27 +01:00
if ( ! ist - > decoded_frame & & ! ( ist - > decoded_frame = avcodec_alloc_frame ( ) ) )
2011-11-23 04:02:17 +01:00
return AVERROR ( ENOMEM ) ;
2011-12-06 01:37:27 +01:00
else
avcodec_get_frame_defaults ( ist - > decoded_frame ) ;
decoded_frame = ist - > decoded_frame ;
2011-11-23 04:02:17 +01:00
pkt - > pts = * pkt_pts ;
pkt - > dts = * pkt_dts ;
* pkt_pts = AV_NOPTS_VALUE ;
2011-12-01 03:12:39 +01:00
if ( pkt - > duration ) {
duration = av_rescale_q ( pkt - > duration , ist - > st - > time_base , AV_TIME_BASE_Q ) ;
} else if ( ist - > st - > codec - > time_base . num ! = 0 ) {
2011-11-23 04:02:17 +01:00
int ticks = ist - > st - > parser ? ist - > st - > parser - > repeat_pict + 1 : ist - > st - > codec - > ticks_per_frame ;
2011-12-01 03:12:39 +01:00
duration = ( ( int64_t ) AV_TIME_BASE *
2011-11-23 04:02:17 +01:00
ist - > st - > codec - > time_base . num * ticks ) /
2011-12-01 03:12:39 +01:00
ist - > st - > codec - > time_base . den ;
}
if ( * pkt_dts ! = AV_NOPTS_VALUE & & duration ) {
* pkt_dts + = duration ;
2011-11-23 04:02:17 +01:00
} else
* pkt_dts = AV_NOPTS_VALUE ;
2007-03-12 15:35:36 +01:00
2011-11-23 04:02:17 +01:00
ret = avcodec_decode_video2 ( ist - > st - > codec ,
decoded_frame , got_output , pkt ) ;
if ( ret < 0 )
2011-12-06 01:37:27 +01:00
return ret ;
2007-08-04 01:25:03 +02:00
2011-11-23 04:02:17 +01:00
quality = same_quant ? decoded_frame - > quality : 0 ;
if ( ! * got_output ) {
/* no picture yet */
2011-11-24 02:08:21 +01:00
return ret ;
2011-11-23 04:02:17 +01:00
}
2007-03-12 15:35:36 +01:00
2011-12-03 21:20:50 +01:00
best_effort_timestamp = av_opt_ptr ( avcodec_get_frame_class ( ) , decoded_frame , " best_effort_timestamp " ) ;
if ( * best_effort_timestamp ! = AV_NOPTS_VALUE )
ist - > next_pts = ist - > pts = * best_effort_timestamp ;
2007-03-12 15:35:36 +01:00
2011-12-01 03:12:39 +01:00
ist - > next_pts + = duration ;
2011-11-23 04:02:17 +01:00
pkt - > size = 0 ;
2007-03-12 15:35:36 +01:00
2011-11-23 04:02:17 +01:00
pre_process_video_frame ( ist , ( AVPicture * ) decoded_frame , & buffer_to_free ) ;
2007-03-12 15:35:36 +01:00
2011-02-14 23:02:10 +01:00
# if CONFIG_AVFILTER
2011-12-03 21:20:50 +01:00
frame_sample_aspect = av_opt_ptr ( avcodec_get_frame_class ( ) , decoded_frame , " sample_aspect_ratio " ) ;
2011-11-23 04:02:17 +01:00
for ( i = 0 ; i < nb_output_streams ; i + + ) {
2011-11-23 23:20:20 +01:00
OutputStream * ost = ost = & output_streams [ i ] ;
if ( check_output_constraints ( ist , ost ) ) {
2011-12-03 21:20:50 +01:00
if ( ! frame_sample_aspect - > num )
* frame_sample_aspect = ist - > st - > sample_aspect_ratio ;
2011-11-23 23:20:20 +01:00
decoded_frame - > pts = ist - > pts ;
2011-12-27 05:34:50 +01:00
if ( ist - > dr1 & & decoded_frame - > type = = FF_BUFFER_TYPE_USER ) {
2011-12-26 05:50:25 +01:00
FrameBuffer * buf = decoded_frame - > opaque ;
AVFilterBufferRef * fb = avfilter_get_video_buffer_ref_from_arrays (
decoded_frame - > data , decoded_frame - > linesize ,
AV_PERM_READ | AV_PERM_PRESERVE ,
ist - > st - > codec - > width , ist - > st - > codec - > height ,
ist - > st - > codec - > pix_fmt ) ;
avfilter_copy_frame_props ( fb , decoded_frame ) ;
fb - > pts = ist - > pts ;
fb - > buf - > priv = buf ;
fb - > buf - > free = filter_release_buffer ;
buf - > refcount + + ;
av_buffersrc_buffer ( ost - > input_video_filter , fb ) ;
} else
2011-12-15 23:54:29 +01:00
if ( ( av_vsrc_buffer_add_frame ( ost - > input_video_filter , decoded_frame , AV_VSRC_BUF_FLAG_OVERWRITE ) ) < 0 ) {
av_log ( 0 , AV_LOG_FATAL , " Failed to inject frame into filter network \n " ) ;
exit_program ( 1 ) ;
}
2011-11-23 23:20:20 +01:00
}
2007-03-12 15:35:36 +01:00
}
2011-11-23 04:02:17 +01:00
# endif
2005-12-17 19:14:38 +01:00
2011-11-23 04:02:17 +01:00
rate_emu_sleep ( ist ) ;
2005-12-17 19:14:38 +01:00
2011-11-23 04:02:17 +01:00
for ( i = 0 ; i < nb_output_streams ; i + + ) {
OutputStream * ost = & output_streams [ i ] ;
int frame_size ;
if ( ! check_output_constraints ( ist , ost ) | | ! ost - > encoding_needed )
continue ;
# if CONFIG_AVFILTER
if ( ost - > input_video_filter ) {
2011-12-06 17:03:07 +01:00
frame_available = av_buffersink_poll_frame ( ost - > output_video_filter ) ;
2011-11-23 04:02:17 +01:00
}
while ( frame_available ) {
if ( ost - > output_video_filter ) {
AVRational ist_pts_tb = ost - > output_video_filter - > inputs [ 0 ] - > time_base ;
2011-12-06 16:01:21 +01:00
if ( av_buffersink_get_buffer_ref ( ost - > output_video_filter , & ost - > picref , 0 ) < 0 ) {
av_log ( 0 , AV_LOG_WARNING , " AV Filter told us it has a frame available but failed to output one \n " ) ;
2011-11-23 04:02:17 +01:00
goto cont ;
2011-12-06 16:01:21 +01:00
}
2011-12-06 01:37:27 +01:00
if ( ! ist - > filtered_frame & & ! ( ist - > filtered_frame = avcodec_alloc_frame ( ) ) ) {
av_free ( buffer_to_free ) ;
return AVERROR ( ENOMEM ) ;
} else
avcodec_get_frame_defaults ( ist - > filtered_frame ) ;
filtered_frame = ist - > filtered_frame ;
2011-11-23 04:02:17 +01:00
* filtered_frame = * decoded_frame ; //for me_threshold
if ( ost - > picref ) {
avfilter_fill_frame_from_video_buffer_ref ( filtered_frame , ost - > picref ) ;
ist - > pts = av_rescale_q ( ost - > picref - > pts , ist_pts_tb , AV_TIME_BASE_Q ) ;
2004-06-22 23:14:01 +02:00
}
}
2011-11-23 04:02:17 +01:00
if ( ost - > picref - > video & & ! ost - > frame_aspect_ratio )
ost - > st - > codec - > sample_aspect_ratio = ost - > picref - > video - > sample_aspect_ratio ;
# else
filtered_frame = decoded_frame ;
# endif
do_video_out ( output_files [ ost - > file_index ] . ctx , ost , ist , filtered_frame , & frame_size ,
same_quant ? quality : ost - > st - > codec - > global_quality ) ;
if ( vstats_filename & & frame_size )
do_video_stats ( output_files [ ost - > file_index ] . ctx , ost , frame_size ) ;
# if CONFIG_AVFILTER
cont :
2011-12-06 17:03:07 +01:00
frame_available = ost - > output_video_filter & & av_buffersink_poll_frame ( ost - > output_video_filter ) ;
2011-11-23 04:02:17 +01:00
avfilter_unref_buffer ( ost - > picref ) ;
2004-06-22 23:14:01 +02:00
}
2011-11-23 04:02:17 +01:00
# endif
2004-06-22 23:14:01 +02:00
}
2005-12-17 19:14:38 +01:00
2011-11-23 04:02:17 +01:00
av_free ( buffer_to_free ) ;
return ret ;
2003-12-15 15:43:44 +01:00
}
2011-11-23 04:02:17 +01:00
static int transcode_subtitles ( InputStream * ist , AVPacket * pkt , int * got_output )
2007-08-20 10:12:08 +02:00
{
2011-11-23 04:02:17 +01:00
AVSubtitle subtitle ;
int i , ret = avcodec_decode_subtitle2 ( ist - > st - > codec ,
& subtitle , got_output , pkt ) ;
if ( ret < 0 )
return ret ;
if ( ! * got_output )
2011-11-24 02:08:21 +01:00
return ret ;
2011-11-23 04:02:17 +01:00
rate_emu_sleep ( ist ) ;
for ( i = 0 ; i < nb_output_streams ; i + + ) {
OutputStream * ost = & output_streams [ i ] ;
if ( ! check_output_constraints ( ist , ost ) | | ! ost - > encoding_needed )
continue ;
do_subtitle_out ( output_files [ ost - > file_index ] . ctx , ost , ist , & subtitle , pkt - > pts ) ;
}
avsubtitle_free ( & subtitle ) ;
2011-11-24 02:08:21 +01:00
return ret ;
2007-08-20 10:12:08 +02:00
}
2003-12-15 15:43:44 +01:00
/* pkt = NULL means EOF (needed to flush decoder buffers) */
2011-11-24 02:08:21 +01:00
static int output_packet ( InputStream * ist ,
2011-08-30 15:03:53 +02:00
OutputStream * ost_table , int nb_ostreams ,
2004-04-27 01:06:29 +02:00
const AVPacket * pkt )
2003-12-15 15:43:44 +01:00
{
2011-09-29 01:03:02 +02:00
int ret = 0 , i ;
2011-05-10 07:53:46 +02:00
int got_output ;
2011-11-10 14:59:00 +01:00
int64_t pkt_dts = AV_NOPTS_VALUE ;
2010-10-10 04:17:26 +02:00
int64_t pkt_pts = AV_NOPTS_VALUE ;
2010-05-07 11:43:21 +02:00
2009-04-10 14:53:22 +02:00
AVPacket avpkt ;
2011-11-24 02:08:21 +01:00
if ( ist - > next_pts = = AV_NOPTS_VALUE )
ist - > next_pts = ist - > pts ;
2008-02-17 20:08:15 +01:00
2003-12-15 15:43:44 +01:00
if ( pkt = = NULL ) {
/* EOF handling */
2009-04-12 00:04:52 +02:00
av_init_packet ( & avpkt ) ;
2009-04-10 14:53:22 +02:00
avpkt . data = NULL ;
avpkt . size = 0 ;
2003-12-15 15:43:44 +01:00
goto handle_eof ;
2009-04-12 00:04:52 +02:00
} else {
avpkt = * pkt ;
2003-12-15 15:43:44 +01:00
}
2011-12-30 03:46:24 +01:00
if ( pkt - > dts ! = AV_NOPTS_VALUE ) {
if ( ist - > st - > codec - > codec_type ! = AVMEDIA_TYPE_VIDEO | | ! ist - > decoding_needed )
2011-11-10 14:59:00 +01:00
ist - > next_pts = ist - > pts = av_rescale_q ( pkt - > dts , ist - > st - > time_base , AV_TIME_BASE_Q ) ;
pkt_dts = av_rescale_q ( pkt - > dts , ist - > st - > time_base , AV_TIME_BASE_Q ) ;
}
2010-10-10 04:17:26 +02:00
if ( pkt - > pts ! = AV_NOPTS_VALUE )
pkt_pts = av_rescale_q ( pkt - > pts , ist - > st - > time_base , AV_TIME_BASE_Q ) ;
2008-02-17 18:55:53 +01:00
2011-12-30 03:46:24 +01:00
// while we have more to decode or while the decoder did output something on EOF
2011-11-23 04:02:17 +01:00
while ( ist - > decoding_needed & & ( avpkt . size > 0 | | ( ! pkt & & got_output ) ) ) {
2003-12-15 15:43:44 +01:00
handle_eof :
2008-02-15 22:45:12 +01:00
2011-11-24 02:08:21 +01:00
ist - > pts = ist - > next_pts ;
if ( avpkt . size & & avpkt . size ! = pkt - > size ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , ist - > showed_multi_packet_warning ? AV_LOG_VERBOSE : AV_LOG_WARNING ,
" Multiple frames in a packet from stream %d \n " , pkt - > stream_index ) ;
2011-11-24 02:08:21 +01:00
ist - > showed_multi_packet_warning = 1 ;
}
2008-02-17 20:38:47 +01:00
2011-12-30 03:46:24 +01:00
switch ( ist - > st - > codec - > codec_type ) {
2011-11-23 04:02:17 +01:00
case AVMEDIA_TYPE_AUDIO :
ret = transcode_audio ( ist , & avpkt , & got_output ) ;
break ;
case AVMEDIA_TYPE_VIDEO :
ret = transcode_video ( ist , & avpkt , & got_output , & pkt_pts , & pkt_dts ) ;
break ;
case AVMEDIA_TYPE_SUBTITLE :
ret = transcode_subtitles ( ist , & avpkt , & got_output ) ;
2010-03-19 08:44:38 +01:00
break ;
2011-11-23 04:02:17 +01:00
default :
return - 1 ;
2007-03-12 15:35:36 +01:00
}
2003-12-15 15:43:44 +01:00
2011-11-23 04:02:17 +01:00
if ( ret < 0 )
return ret ;
2011-12-13 19:46:29 +01:00
avpkt . dts =
avpkt . pts = AV_NOPTS_VALUE ;
2011-11-24 02:08:21 +01:00
// touch data and size only if not EOF
if ( pkt ) {
if ( ist - > st - > codec - > codec_type ! = AVMEDIA_TYPE_AUDIO )
ret = avpkt . size ;
avpkt . data + = ret ;
avpkt . size - = ret ;
}
2011-11-23 04:02:17 +01:00
if ( ! got_output ) {
2011-11-24 02:08:21 +01:00
continue ;
2011-06-06 04:03:09 +02:00
}
2011-11-23 04:02:17 +01:00
}
2011-06-06 04:03:09 +02:00
2011-11-23 04:02:17 +01:00
/* handle stream copy */
if ( ! ist - > decoding_needed ) {
rate_emu_sleep ( ist ) ;
2011-12-01 02:44:19 +01:00
ist - > pts = ist - > next_pts ;
2011-11-23 04:02:17 +01:00
switch ( ist - > st - > codec - > codec_type ) {
case AVMEDIA_TYPE_AUDIO :
ist - > next_pts + = ( ( int64_t ) AV_TIME_BASE * ist - > st - > codec - > frame_size ) /
ist - > st - > codec - > sample_rate ;
break ;
case AVMEDIA_TYPE_VIDEO :
2011-12-03 15:03:49 +01:00
if ( pkt - > duration ) {
ist - > next_pts + = av_rescale_q ( pkt - > duration , ist - > st - > time_base , AV_TIME_BASE_Q ) ;
} else if ( ist - > st - > codec - > time_base . num ! = 0 ) {
2011-12-30 03:46:24 +01:00
int ticks = ist - > st - > parser ? ist - > st - > parser - > repeat_pict + 1 : ist - > st - > codec - > ticks_per_frame ;
2011-11-23 04:02:17 +01:00
ist - > next_pts + = ( ( int64_t ) AV_TIME_BASE *
ist - > st - > codec - > time_base . num * ticks ) /
ist - > st - > codec - > time_base . den ;
2005-03-23 02:59:17 +01:00
}
2011-11-23 04:02:17 +01:00
break ;
2007-03-12 15:35:36 +01:00
}
2011-11-23 04:02:17 +01:00
}
for ( i = 0 ; pkt & & i < nb_ostreams ; i + + ) {
2011-11-24 02:08:21 +01:00
OutputStream * ost = & ost_table [ i ] ;
2005-03-23 02:59:17 +01:00
2011-11-23 04:02:17 +01:00
if ( ! check_output_constraints ( ist , ost ) | | ost - > encoding_needed )
continue ;
2010-05-07 11:43:21 +02:00
2011-11-23 04:02:17 +01:00
do_streamcopy ( ist , ost , pkt ) ;
2007-03-12 15:35:36 +01:00
}
2005-12-17 19:14:38 +01:00
2003-12-15 15:43:44 +01:00
return 0 ;
}
2011-08-30 14:19:39 +02:00
static void print_sdp ( OutputFile * output_files , int n )
2007-08-20 10:12:08 +02:00
{
char sdp [ 2048 ] ;
2011-08-30 14:19:39 +02:00
int i ;
2011-12-30 03:46:24 +01:00
AVFormatContext * * avc = av_malloc ( sizeof ( * avc ) * n ) ;
2011-08-30 14:19:39 +02:00
if ( ! avc )
exit_program ( 1 ) ;
for ( i = 0 ; i < n ; i + + )
avc [ i ] = output_files [ i ] . ctx ;
2007-08-20 10:12:08 +02:00
2011-04-08 11:36:12 +02:00
av_sdp_create ( avc , n , sdp , sizeof ( sdp ) ) ;
2007-08-20 10:12:08 +02:00
printf ( " SDP: \n %s \n " , sdp ) ;
2008-11-15 13:32:38 +01:00
fflush ( stdout ) ;
2011-08-30 14:19:39 +02:00
av_freep ( & avc ) ;
2007-08-20 10:12:08 +02:00
}
2003-12-15 15:43:44 +01:00
2011-08-30 15:53:55 +02:00
static int init_input_stream ( int ist_index , OutputStream * output_streams , int nb_output_streams ,
char * error , int error_len )
{
InputStream * ist = & input_streams [ ist_index ] ;
if ( ist - > decoding_needed ) {
AVCodec * codec = ist - > dec ;
if ( ! codec ) {
2011-11-07 02:41:01 +01:00
snprintf ( error , error_len , " Decoder (codec %s) not found for input stream #%d:%d " ,
2011-08-30 15:53:55 +02:00
avcodec_get_name ( ist - > st - > codec - > codec_id ) , ist - > file_index , ist - > st - > index ) ;
return AVERROR ( EINVAL ) ;
}
2011-12-26 05:50:25 +01:00
2011-12-27 05:22:44 +01:00
ist - > dr1 = codec - > capabilities & CODEC_CAP_DR1 ;
if ( codec - > type = = AVMEDIA_TYPE_VIDEO & & ist - > dr1 ) {
2011-12-26 05:50:25 +01:00
ist - > st - > codec - > get_buffer = codec_get_buffer ;
ist - > st - > codec - > release_buffer = codec_release_buffer ;
ist - > st - > codec - > opaque = ist ;
}
2011-08-30 15:53:55 +02:00
if ( avcodec_open2 ( ist - > st - > codec , codec , & ist - > opts ) < 0 ) {
2011-11-07 02:41:01 +01:00
snprintf ( error , error_len , " Error while opening decoder for input stream #%d:%d " ,
2011-08-30 15:53:55 +02:00
ist - > file_index , ist - > st - > index ) ;
return AVERROR ( EINVAL ) ;
}
assert_codec_experimental ( ist - > st - > codec , 0 ) ;
assert_avoptions ( ist - > opts ) ;
}
2011-12-30 03:46:24 +01:00
ist - > pts = ist - > st - > avg_frame_rate . num ? - ist - > st - > codec - > has_b_frames * AV_TIME_BASE / av_q2d ( ist - > st - > avg_frame_rate ) : 0 ;
2011-08-30 15:53:55 +02:00
ist - > next_pts = AV_NOPTS_VALUE ;
ist - > is_start = 1 ;
return 0 ;
}
2011-09-12 11:44:14 +02:00
static int transcode_init ( OutputFile * output_files , int nb_output_files ,
InputFile * input_files , int nb_input_files )
2001-07-22 16:37:44 +02:00
{
2011-09-11 23:35:35 +02:00
int ret = 0 , i , j , k ;
2011-11-22 02:54:50 +01:00
AVFormatContext * oc ;
2001-07-22 16:37:44 +02:00
AVCodecContext * codec , * icodec ;
2011-08-30 15:03:53 +02:00
OutputStream * ost ;
2011-06-23 19:14:08 +02:00
InputStream * ist ;
2009-03-11 07:06:18 +01:00
char error [ 1024 ] ;
2007-08-20 10:12:08 +02:00
int want_sdp = 1 ;
2011-08-30 15:08:02 +02:00
2011-09-05 22:10:26 +02:00
/* init framerate emulation */
for ( i = 0 ; i < nb_input_files ; i + + ) {
InputFile * ifile = & input_files [ i ] ;
if ( ifile - > rate_emu )
for ( j = 0 ; j < ifile - > nb_streams ; j + + )
input_streams [ j + ifile - > ist_index ] . start = av_gettime ( ) ;
}
2001-07-22 16:37:44 +02:00
/* output stream init */
2011-11-22 02:54:50 +01:00
for ( i = 0 ; i < nb_output_files ; i + + ) {
oc = output_files [ i ] . ctx ;
if ( ! oc - > nb_streams & & ! ( oc - > oformat - > flags & AVFMT_NOSTREAMS ) ) {
av_dump_format ( oc , i , oc - > filename , 1 ) ;
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_ERROR , " Output file #%d does not contain any stream \n " , i ) ;
2011-08-30 16:03:51 +02:00
return AVERROR ( EINVAL ) ;
2006-11-05 21:08:26 +01:00
}
2001-07-22 16:37:44 +02:00
}
/* for each output stream, we compute the right encoding parameters */
2011-08-30 15:03:53 +02:00
for ( i = 0 ; i < nb_output_streams ; i + + ) {
ost = & output_streams [ i ] ;
2011-11-22 02:54:50 +01:00
oc = output_files [ ost - > file_index ] . ctx ;
2011-05-22 22:12:35 +02:00
ist = & input_streams [ ost - > source_index ] ;
2001-07-22 16:37:44 +02:00
2011-11-04 01:44:06 +01:00
if ( ost - > attachment_filename )
continue ;
2011-11-22 02:54:50 +01:00
codec = ost - > st - > codec ;
2005-07-18 00:24:36 +02:00
icodec = ist - > st - > codec ;
2001-07-22 16:37:44 +02:00
2011-11-22 02:54:50 +01:00
ost - > st - > disposition = ist - > st - > disposition ;
codec - > bits_per_raw_sample = icodec - > bits_per_raw_sample ;
2009-05-12 02:47:19 +02:00
codec - > chroma_sample_location = icodec - > chroma_sample_location ;
2008-03-07 20:25:09 +01:00
2011-10-26 02:09:31 +02:00
if ( ost - > stream_copy ) {
2010-06-08 21:27:29 +02:00
uint64_t extra_size = ( uint64_t ) icodec - > extradata_size + FF_INPUT_BUFFER_PADDING_SIZE ;
2011-08-30 15:57:50 +02:00
if ( extra_size > INT_MAX ) {
2011-08-30 16:03:51 +02:00
return AVERROR ( EINVAL ) ;
2011-08-30 15:57:50 +02:00
}
2010-06-08 21:27:29 +02:00
2002-10-11 11:19:34 +02:00
/* if stream_copy is selected, no need to decode or encode */
2011-11-22 02:54:50 +01:00
codec - > codec_id = icodec - > codec_id ;
2002-10-11 11:19:34 +02:00
codec - > codec_type = icodec - > codec_type ;
2007-08-04 18:03:39 +02:00
2011-11-22 02:54:50 +01:00
if ( ! codec - > codec_tag ) {
if ( ! oc - > oformat - > codec_tag | |
av_codec_get_id ( oc - > oformat - > codec_tag , icodec - > codec_tag ) = = codec - > codec_id | |
av_codec_get_tag ( oc - > oformat - > codec_tag , icodec - > codec_id ) < = 0 )
2007-08-04 18:03:39 +02:00
codec - > codec_tag = icodec - > codec_tag ;
}
2011-11-22 02:54:50 +01:00
codec - > bit_rate = icodec - > bit_rate ;
2010-10-07 03:57:35 +02:00
codec - > rc_max_rate = icodec - > rc_max_rate ;
codec - > rc_buffer_size = icodec - > rc_buffer_size ;
2011-12-23 03:00:12 +01:00
codec - > field_order = icodec - > field_order ;
2011-11-22 02:54:50 +01:00
codec - > extradata = av_mallocz ( extra_size ) ;
2011-08-30 15:57:50 +02:00
if ( ! codec - > extradata ) {
2011-08-30 16:03:51 +02:00
return AVERROR ( ENOMEM ) ;
2011-08-30 15:57:50 +02:00
}
2010-06-08 21:27:29 +02:00
memcpy ( codec - > extradata , icodec - > extradata , icodec - > extradata_size ) ;
2005-03-24 02:47:45 +01:00
codec - > extradata_size = icodec - > extradata_size ;
2011-07-25 20:48:55 +02:00
codec - > time_base = ist - > st - > time_base ;
2011-11-22 02:54:50 +01:00
if ( ! strcmp ( oc - > oformat - > name , " avi " ) ) {
2011-12-01 03:06:16 +01:00
if ( copy_tb < 0 & & av_q2d ( icodec - > time_base ) * icodec - > ticks_per_frame > 2 * av_q2d ( ist - > st - > time_base )
& & av_q2d ( ist - > st - > time_base ) < 1.0 / 500
| | copy_tb = = 0 ) {
2011-07-25 20:48:55 +02:00
codec - > time_base = icodec - > time_base ;
codec - > time_base . num * = icodec - > ticks_per_frame ;
codec - > time_base . den * = 2 ;
}
2011-12-05 03:19:28 +01:00
} else if ( ! ( oc - > oformat - > flags & AVFMT_VARIABLE_FPS )
& & strcmp ( oc - > oformat - > name , " mov " ) & & strcmp ( oc - > oformat - > name , " mp4 " ) & & strcmp ( oc - > oformat - > name , " 3gp " )
& & strcmp ( oc - > oformat - > name , " 3g2 " ) & & strcmp ( oc - > oformat - > name , " psp " ) & & strcmp ( oc - > oformat - > name , " ipod " )
) {
2011-12-01 03:06:16 +01:00
if ( copy_tb < 0 & & av_q2d ( icodec - > time_base ) * icodec - > ticks_per_frame > av_q2d ( ist - > st - > time_base )
& & av_q2d ( ist - > st - > time_base ) < 1.0 / 500
| | copy_tb = = 0 ) {
2011-07-25 20:48:55 +02:00
codec - > time_base = icodec - > time_base ;
codec - > time_base . num * = icodec - > ticks_per_frame ;
}
}
av_reduce ( & codec - > time_base . num , & codec - > time_base . den ,
codec - > time_base . num , codec - > time_base . den , INT_MAX ) ;
2011-12-30 03:46:24 +01:00
switch ( codec - > codec_type ) {
2010-03-31 01:30:55 +02:00
case AVMEDIA_TYPE_AUDIO :
2011-12-30 03:46:24 +01:00
if ( audio_volume ! = 256 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " -acodec copy and -vol are incompatible (frames are not decoded) \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2008-07-12 13:43:21 +02:00
}
2011-11-22 02:54:50 +01:00
codec - > channel_layout = icodec - > channel_layout ;
codec - > sample_rate = icodec - > sample_rate ;
codec - > channels = icodec - > channels ;
codec - > frame_size = icodec - > frame_size ;
2011-03-24 17:00:21 +01:00
codec - > audio_service_type = icodec - > audio_service_type ;
2011-11-22 02:54:50 +01:00
codec - > block_align = icodec - > block_align ;
2002-10-11 11:19:34 +02:00
break ;
2010-03-31 01:30:55 +02:00
case AVMEDIA_TYPE_VIDEO :
2011-11-22 02:54:50 +01:00
codec - > pix_fmt = icodec - > pix_fmt ;
codec - > width = icodec - > width ;
codec - > height = icodec - > height ;
codec - > has_b_frames = icodec - > has_b_frames ;
2011-04-17 01:47:24 +02:00
if ( ! codec - > sample_aspect_ratio . num ) {
2011-11-22 02:54:50 +01:00
codec - > sample_aspect_ratio =
2011-04-17 01:47:24 +02:00
ost - > st - > sample_aspect_ratio =
ist - > st - > sample_aspect_ratio . num ? ist - > st - > sample_aspect_ratio :
ist - > st - > codec - > sample_aspect_ratio . num ?
ist - > st - > codec - > sample_aspect_ratio : ( AVRational ) { 0 , 1 } ;
}
2011-11-05 23:43:01 +01:00
ost - > st - > avg_frame_rate = ist - > st - > avg_frame_rate ;
2002-10-11 11:19:34 +02:00
break ;
2010-03-31 01:30:55 +02:00
case AVMEDIA_TYPE_SUBTITLE :
2011-11-22 02:54:50 +01:00
codec - > width = icodec - > width ;
2009-01-18 00:54:27 +01:00
codec - > height = icodec - > height ;
2005-06-03 16:31:45 +02:00
break ;
2011-04-14 13:32:36 +02:00
case AVMEDIA_TYPE_DATA :
2011-09-28 01:31:38 +02:00
case AVMEDIA_TYPE_ATTACHMENT :
2011-04-14 13:32:36 +02:00
break ;
2002-10-11 11:19:34 +02:00
default :
2007-07-02 09:43:23 +02:00
abort ( ) ;
2002-10-11 11:19:34 +02:00
}
} else {
2011-06-16 06:24:54 +02:00
if ( ! ost - > enc )
ost - > enc = avcodec_find_encoder ( ost - > st - > codec - > codec_id ) ;
2011-11-22 02:54:50 +01:00
2011-10-10 03:41:49 +02:00
ist - > decoding_needed = 1 ;
ost - > encoding_needed = 1 ;
2011-11-22 02:54:50 +01:00
2011-12-30 03:46:24 +01:00
switch ( codec - > codec_type ) {
2010-03-31 01:30:55 +02:00
case AVMEDIA_TYPE_AUDIO :
2011-11-22 02:54:50 +01:00
ost - > fifo = av_fifo_alloc ( 1024 ) ;
2011-08-30 15:57:50 +02:00
if ( ! ost - > fifo ) {
2011-08-30 16:03:51 +02:00
return AVERROR ( ENOMEM ) ;
2011-08-30 15:57:50 +02:00
}
2011-10-26 02:09:31 +02:00
if ( ! codec - > sample_rate )
2011-06-15 08:00:03 +02:00
codec - > sample_rate = icodec - > sample_rate ;
2011-06-16 06:24:54 +02:00
choose_sample_rate ( ost - > st , ost - > enc ) ;
2011-12-30 03:46:24 +01:00
codec - > time_base = ( AVRational ) { 1 , codec - > sample_rate } ;
2011-11-22 02:54:50 +01:00
2011-06-15 08:00:03 +02:00
if ( codec - > sample_fmt = = AV_SAMPLE_FMT_NONE )
codec - > sample_fmt = icodec - > sample_fmt ;
choose_sample_fmt ( ost - > st , ost - > enc ) ;
2011-11-22 02:54:50 +01:00
2011-11-04 18:54:01 +01:00
if ( ost - > audio_channels_mapped ) {
/* the requested output channel is set to the number of
* - map_channel only if no - ac are specified */
if ( ! codec - > channels ) {
codec - > channels = ost - > audio_channels_mapped ;
codec - > channel_layout = av_get_default_channel_layout ( codec - > channels ) ;
if ( ! codec - > channel_layout ) {
av_log ( NULL , AV_LOG_FATAL , " Unable to find an appropriate channel layout for requested number of channel \n " ) ;
exit_program ( 1 ) ;
}
}
/* fill unused channel mapping with -1 (which means a muted
* channel in case the number of output channels is bigger
* than the number of mapped channel ) */
for ( j = ost - > audio_channels_mapped ; j < FF_ARRAY_ELEMS ( ost - > audio_channels_map ) ; j + + )
ost - > audio_channels_map [ j ] = - 1 ;
} else if ( ! codec - > channels ) {
2011-06-15 08:00:03 +02:00
codec - > channels = icodec - > channels ;
2011-06-29 23:49:44 +02:00
codec - > channel_layout = icodec - > channel_layout ;
}
2011-06-15 08:00:03 +02:00
if ( av_get_channel_layout_nb_channels ( codec - > channel_layout ) ! = codec - > channels )
codec - > channel_layout = 0 ;
2011-11-22 02:54:50 +01:00
ost - > audio_resample = codec - > sample_rate ! = icodec - > sample_rate | | audio_sync_method > 1 ;
ost - > audio_resample | = codec - > sample_fmt ! = icodec - > sample_fmt
| | codec - > channel_layout ! = icodec - > channel_layout ;
icodec - > request_channels = codec - > channels ;
2010-12-12 17:18:50 +01:00
ost - > resample_sample_fmt = icodec - > sample_fmt ;
ost - > resample_sample_rate = icodec - > sample_rate ;
ost - > resample_channels = icodec - > channels ;
2002-10-11 11:19:34 +02:00
break ;
2010-03-31 01:30:55 +02:00
case AVMEDIA_TYPE_VIDEO :
2011-06-15 08:00:03 +02:00
if ( codec - > pix_fmt = = PIX_FMT_NONE )
codec - > pix_fmt = icodec - > pix_fmt ;
choose_pixel_fmt ( ost - > st , ost - > enc ) ;
2009-06-12 10:15:37 +02:00
if ( ost - > st - > codec - > pix_fmt = = PIX_FMT_NONE ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Video pixel format is unknown, stream cannot be encoded \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2009-06-12 10:15:37 +02:00
}
2011-07-17 16:27:14 +02:00
if ( ! codec - > width | | ! codec - > height ) {
codec - > width = icodec - > width ;
codec - > height = icodec - > height ;
}
2011-04-16 23:18:22 +02:00
ost - > video_resample = codec - > width ! = icodec - > width | |
codec - > height ! = icodec - > height | |
codec - > pix_fmt ! = icodec - > pix_fmt ;
2006-04-20 14:57:19 +02:00
if ( ost - > video_resample ) {
2011-12-30 03:46:24 +01:00
codec - > bits_per_raw_sample = frame_bits_per_raw_sample ;
2001-07-22 16:37:44 +02:00
}
2011-07-17 16:27:14 +02:00
2011-11-22 02:54:50 +01:00
ost - > resample_height = icodec - > height ;
ost - > resample_width = icodec - > width ;
ost - > resample_pix_fmt = icodec - > pix_fmt ;
2010-05-07 11:43:21 +02:00
2011-06-15 08:00:03 +02:00
if ( ! ost - > frame_rate . num )
2011-12-30 03:46:24 +01:00
ost - > frame_rate = ist - > st - > r_frame_rate . num ? ist - > st - > r_frame_rate : ( AVRational ) { 25 , 1 } ;
2011-09-11 23:35:35 +02:00
if ( ost - > enc & & ost - > enc - > supported_framerates & & ! ost - > force_fps ) {
2011-06-16 06:24:54 +02:00
int idx = av_find_nearest_q_idx ( ost - > frame_rate , ost - > enc - > supported_framerates ) ;
ost - > frame_rate = ost - > enc - > supported_framerates [ idx ] ;
2011-06-15 08:00:03 +02:00
}
codec - > time_base = ( AVRational ) { ost - > frame_rate . den , ost - > frame_rate . num } ;
2011-12-30 03:46:24 +01:00
if ( av_q2d ( codec - > time_base ) < 0.001 & & video_sync_method
2011-11-22 02:54:50 +01:00
& & ( video_sync_method = = 1 | | ( video_sync_method < 0 & & ! ( oc - > oformat - > flags & AVFMT_VARIABLE_FPS ) ) ) ) {
av_log ( oc , AV_LOG_WARNING , " Frame rate very high for a muxer not effciciently supporting it. \n "
2011-06-20 20:13:26 +02:00
" Please consider specifiying a lower framerate, a different muxer or -vsync 2 \n " ) ;
}
2011-10-05 14:01:46 +02:00
for ( j = 0 ; j < ost - > forced_kf_count ; j + + )
ost - > forced_kf_pts [ j ] = av_rescale_q ( ost - > forced_kf_pts [ j ] ,
AV_TIME_BASE_Q ,
codec - > time_base ) ;
2011-06-15 08:00:03 +02:00
2010-05-07 11:43:21 +02:00
# if CONFIG_AVFILTER
2011-04-03 21:54:57 +02:00
if ( configure_video_filters ( ist , ost ) ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Error opening filters! \n " ) ;
2010-05-07 11:43:21 +02:00
exit ( 1 ) ;
}
# endif
2002-10-11 11:19:34 +02:00
break ;
2010-03-31 01:30:55 +02:00
case AVMEDIA_TYPE_SUBTITLE :
2005-06-03 16:31:45 +02:00
break ;
2002-10-11 11:19:34 +02:00
default :
2007-07-02 09:43:23 +02:00
abort ( ) ;
2005-06-03 16:31:45 +02:00
break ;
2001-07-22 16:37:44 +02:00
}
2002-10-11 11:19:34 +02:00
/* two pass mode */
2011-10-10 03:41:49 +02:00
if ( codec - > codec_id ! = CODEC_ID_H264 & &
2002-10-11 11:19:34 +02:00
( codec - > flags & ( CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2 ) ) ) {
char logfilename [ 1024 ] ;
FILE * f ;
2005-12-17 19:14:38 +01:00
snprintf ( logfilename , sizeof ( logfilename ) , " %s-%d.log " ,
2008-12-26 20:28:42 +01:00
pass_logfilename_prefix ? pass_logfilename_prefix : DEFAULT_PASS_LOGFILENAME_PREFIX ,
i ) ;
2011-10-30 02:26:48 +01:00
if ( codec - > flags & CODEC_FLAG_PASS2 ) {
2010-04-02 00:34:22 +02:00
char * logbuffer ;
size_t logbuffer_size ;
2011-02-07 10:49:37 +01:00
if ( cmdutils_read_file ( logfilename , & logbuffer , & logbuffer_size ) < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Error reading log file '%s' for pass-2 encoding \n " ,
logfilename ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2002-10-11 11:19:34 +02:00
}
codec - > stats_in = logbuffer ;
2002-10-10 19:09:01 +02:00
}
2011-10-30 02:26:48 +01:00
if ( codec - > flags & CODEC_FLAG_PASS1 ) {
f = fopen ( logfilename , " wb " ) ;
if ( ! f ) {
av_log ( NULL , AV_LOG_FATAL , " Cannot write log file '%s' for pass-1 encoding: %s \n " ,
logfilename , strerror ( errno ) ) ;
exit_program ( 1 ) ;
}
ost - > logfile = f ;
}
2002-10-10 19:09:01 +02:00
}
}
2011-12-30 03:46:24 +01:00
if ( codec - > codec_type = = AVMEDIA_TYPE_VIDEO ) {
2011-09-25 16:13:07 +02:00
/* maximum video buffer size is 6-bytes per pixel, plus DPX header size (1664)*/
2011-11-22 02:54:50 +01:00
int size = codec - > width * codec - > height ;
bit_buffer_size = FFMAX ( bit_buffer_size , 7 * size + 10000 ) ;
2004-11-27 18:46:30 +01:00
}
2001-07-22 16:37:44 +02:00
}
2004-11-27 18:46:30 +01:00
if ( ! bit_buffer )
bit_buffer = av_malloc ( bit_buffer_size ) ;
2009-03-11 07:06:18 +01:00
if ( ! bit_buffer ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_ERROR , " Cannot allocate %d bytes output buffer \n " ,
bit_buffer_size ) ;
2011-08-30 16:03:51 +02:00
return AVERROR ( ENOMEM ) ;
2002-10-11 11:19:34 +02:00
}
2001-07-22 16:37:44 +02:00
/* open each encoder */
2011-08-30 15:03:53 +02:00
for ( i = 0 ; i < nb_output_streams ; i + + ) {
ost = & output_streams [ i ] ;
2001-07-22 16:37:44 +02:00
if ( ost - > encoding_needed ) {
2011-11-22 02:54:50 +01:00
AVCodec * codec = ost - > enc ;
2011-05-22 22:12:35 +02:00
AVCodecContext * dec = input_streams [ ost - > source_index ] . st - > codec ;
2001-07-22 16:37:44 +02:00
if ( ! codec ) {
2011-11-07 02:41:01 +01:00
snprintf ( error , sizeof ( error ) , " Encoder (codec %s) not found for output stream #%d:%d " ,
2011-08-17 15:46:15 +02:00
avcodec_get_name ( ost - > st - > codec - > codec_id ) , ost - > file_index , ost - > index ) ;
2009-03-11 07:06:18 +01:00
ret = AVERROR ( EINVAL ) ;
goto dump_format ;
2001-07-22 16:37:44 +02:00
}
2010-11-13 14:57:49 +01:00
if ( dec - > subtitle_header ) {
ost - > st - > codec - > subtitle_header = av_malloc ( dec - > subtitle_header_size ) ;
if ( ! ost - > st - > codec - > subtitle_header ) {
ret = AVERROR ( ENOMEM ) ;
goto dump_format ;
}
memcpy ( ost - > st - > codec - > subtitle_header , dec - > subtitle_header , dec - > subtitle_header_size ) ;
ost - > st - > codec - > subtitle_header_size = dec - > subtitle_header_size ;
}
2011-05-25 17:29:25 +02:00
if ( avcodec_open2 ( ost - > st - > codec , codec , & ost - > opts ) < 0 ) {
2011-11-07 02:41:01 +01:00
snprintf ( error , sizeof ( error ) , " Error while opening encoder for output stream #%d:%d - maybe incorrect parameters such as bit_rate, rate, width or height " ,
2001-07-22 16:37:44 +02:00
ost - > file_index , ost - > index ) ;
2009-03-11 07:06:18 +01:00
ret = AVERROR ( EINVAL ) ;
goto dump_format ;
2001-07-22 16:37:44 +02:00
}
2011-07-12 17:18:42 +02:00
assert_codec_experimental ( ost - > st - > codec , 1 ) ;
2011-05-25 17:29:25 +02:00
assert_avoptions ( ost - > opts ) ;
2011-07-14 09:38:36 +02:00
if ( ost - > st - > codec - > bit_rate & & ost - > st - > codec - > bit_rate < 1000 )
av_log ( NULL , AV_LOG_WARNING , " The bitrate parameter is set too low. "
2011-10-08 21:39:36 +02:00
" It takes bits/s as argument, not kbits/s \n " ) ;
2005-07-18 00:24:36 +02:00
extra_size + = ost - > st - > codec - > extradata_size ;
2011-09-11 23:35:35 +02:00
if ( ost - > st - > codec - > me_threshold )
input_streams [ ost - > source_index ] . st - > codec - > debug | = FF_DEBUG_MV ;
2001-07-22 16:37:44 +02:00
}
}
2011-08-30 15:53:55 +02:00
/* init input streams */
for ( i = 0 ; i < nb_input_streams ; i + + )
2011-09-01 03:46:04 +02:00
if ( ( ret = init_input_stream ( i , output_streams , nb_output_streams , error , sizeof ( error ) ) ) < 0 )
2011-08-30 15:53:55 +02:00
goto dump_format ;
2010-02-02 23:23:09 +01:00
2011-09-11 23:35:35 +02:00
/* discard unused programs */
for ( i = 0 ; i < nb_input_files ; i + + ) {
InputFile * ifile = & input_files [ i ] ;
for ( j = 0 ; j < ifile - > ctx - > nb_programs ; j + + ) {
AVProgram * p = ifile - > ctx - > programs [ j ] ;
int discard = AVDISCARD_ALL ;
for ( k = 0 ; k < p - > nb_stream_indexes ; k + + )
if ( ! input_streams [ ifile - > ist_index + p - > stream_index [ k ] ] . discard ) {
discard = AVDISCARD_DEFAULT ;
2011-04-24 22:48:42 +02:00
break ;
}
2011-09-11 23:35:35 +02:00
p - > discard = discard ;
2001-07-22 16:37:44 +02:00
}
}
/* open files and write file headers */
2011-08-30 14:19:39 +02:00
for ( i = 0 ; i < nb_output_files ; i + + ) {
2011-11-22 02:54:50 +01:00
oc = output_files [ i ] . ctx ;
oc - > interrupt_callback = int_cb ;
if ( avformat_write_header ( oc , & output_files [ i ] . opts ) < 0 ) {
2009-03-11 07:06:18 +01:00
snprintf ( error , sizeof ( error ) , " Could not write header for output file #%d (incorrect codec parameters ?) " , i ) ;
2007-02-13 19:26:14 +01:00
ret = AVERROR ( EINVAL ) ;
2009-03-11 07:06:18 +01:00
goto dump_format ;
2001-09-25 01:22:25 +02:00
}
2011-08-30 14:19:39 +02:00
// assert_avoptions(output_files[i].opts);
2011-11-22 02:54:50 +01:00
if ( strcmp ( oc - > oformat - > name , " rtp " ) ) {
2007-08-20 10:12:08 +02:00
want_sdp = 0 ;
}
}
2009-03-11 07:06:18 +01:00
dump_format :
/* dump the file output parameters - cannot be done before in case
of stream copy */
2011-11-22 02:54:50 +01:00
for ( i = 0 ; i < nb_output_files ; i + + ) {
2011-08-30 14:19:39 +02:00
av_dump_format ( output_files [ i ] . ctx , i , output_files [ i ] . ctx - > filename , 1 ) ;
2009-03-11 07:06:18 +01:00
}
/* dump the stream mapping */
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_INFO , " Stream mapping: \n " ) ;
for ( i = 0 ; i < nb_output_streams ; i + + ) {
ost = & output_streams [ i ] ;
2011-11-04 01:44:06 +01:00
if ( ost - > attachment_filename ) {
/* an attached file */
av_log ( NULL , AV_LOG_INFO , " File %s -> Stream #%d:%d \n " ,
ost - > attachment_filename , ost - > file_index , ost - > index ) ;
continue ;
2009-03-11 07:06:18 +01:00
}
2011-11-07 02:41:01 +01:00
av_log ( NULL , AV_LOG_INFO , " Stream #%d:%d -> #%d:%d " ,
2011-09-27 02:14:37 +02:00
input_streams [ ost - > source_index ] . file_index ,
input_streams [ ost - > source_index ] . st - > index ,
ost - > file_index ,
ost - > index ) ;
2011-11-04 18:54:01 +01:00
if ( ost - > audio_channels_mapped ) {
av_log ( NULL , AV_LOG_INFO , " [ch: " ) ;
for ( j = 0 ; j < ost - > audio_channels_mapped ; j + + )
if ( ost - > audio_channels_map [ j ] = = - 1 )
av_log ( NULL , AV_LOG_INFO , " M " ) ;
else
av_log ( NULL , AV_LOG_INFO , " %d " , ost - > audio_channels_map [ j ] ) ;
av_log ( NULL , AV_LOG_INFO , " ] " ) ;
}
2011-09-27 02:14:37 +02:00
if ( ost - > sync_ist ! = & input_streams [ ost - > source_index ] )
2011-11-07 02:41:01 +01:00
av_log ( NULL , AV_LOG_INFO , " [sync #%d:%d] " ,
2011-09-27 02:14:37 +02:00
ost - > sync_ist - > file_index ,
ost - > sync_ist - > st - > index ) ;
2011-10-26 02:09:31 +02:00
if ( ost - > stream_copy )
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_INFO , " (copy) " ) ;
else
av_log ( NULL , AV_LOG_INFO , " (%s -> %s) " , input_streams [ ost - > source_index ] . dec ?
input_streams [ ost - > source_index ] . dec - > name : " ? " ,
ost - > enc ? ost - > enc - > name : " ? " ) ;
av_log ( NULL , AV_LOG_INFO , " \n " ) ;
2009-03-11 07:06:18 +01:00
}
if ( ret ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_ERROR , " %s \n " , error ) ;
2011-08-30 16:03:51 +02:00
return ret ;
2009-03-11 07:06:18 +01:00
}
2007-08-20 10:12:08 +02:00
if ( want_sdp ) {
print_sdp ( output_files , nb_output_files ) ;
2001-07-22 16:37:44 +02:00
}
2011-08-30 16:03:51 +02:00
return 0 ;
}
/*
* The following code is the main loop of the file converter
*/
2011-09-12 11:44:14 +02:00
static int transcode ( OutputFile * output_files , int nb_output_files ,
InputFile * input_files , int nb_input_files )
2011-08-30 16:03:51 +02:00
{
int ret , i ;
AVFormatContext * is , * os ;
OutputStream * ost ;
InputStream * ist ;
uint8_t * no_packet ;
2011-12-30 03:46:24 +01:00
int no_packet_count = 0 ;
2011-08-30 16:03:51 +02:00
int64_t timer_start ;
int key ;
if ( ! ( no_packet = av_mallocz ( nb_input_files ) ) )
exit_program ( 1 ) ;
ret = transcode_init ( output_files , nb_output_files , input_files , nb_input_files ) ;
if ( ret < 0 )
goto fail ;
2011-03-07 17:23:32 +01:00
if ( ! using_stdin ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_INFO , " Press [q] to stop, [?] for help \n " ) ;
2004-03-14 20:40:43 +01:00
}
2001-09-25 01:22:25 +02:00
2007-03-16 17:13:54 +01:00
timer_start = av_gettime ( ) ;
2002-05-09 03:06:59 +02:00
2011-12-30 03:46:24 +01:00
for ( ; received_sigterm = = 0 ; ) {
2001-07-22 16:37:44 +02:00
int file_index , ist_index ;
AVPacket pkt ;
2011-08-30 04:45:46 +02:00
int64_t ipts_min ;
2004-07-25 02:22:20 +02:00
double opts_min ;
2011-10-08 17:32:06 +02:00
int64_t cur_time = av_gettime ( ) ;
2004-06-30 00:56:54 +02:00
2011-12-30 03:46:24 +01:00
ipts_min = INT64_MAX ;
opts_min = 1e100 ;
2001-09-25 01:22:25 +02:00
/* if 'q' pressed, exits */
2003-08-29 22:51:10 +02:00
if ( ! using_stdin ) {
2011-10-08 18:36:15 +02:00
static int64_t last_time ;
2011-10-08 17:21:25 +02:00
if ( received_nb_signals )
2004-03-14 20:40:43 +01:00
break ;
2002-05-30 04:38:57 +02:00
/* read_key() returns 0 on EOF */
2011-10-08 18:36:15 +02:00
if ( cur_time - last_time > = 100000 & & ! run_as_daemon ) {
key = read_key ( ) ;
last_time = cur_time ;
} else
key = - 1 ;
2002-05-30 04:38:57 +02:00
if ( key = = ' q ' )
break ;
2011-09-27 02:14:37 +02:00
if ( key = = ' + ' ) av_log_set_level ( av_log_get_level ( ) + 10 ) ;
if ( key = = ' - ' ) av_log_set_level ( av_log_get_level ( ) - 10 ) ;
2011-05-14 02:54:28 +02:00
if ( key = = ' s ' ) qp_hist ^ = 1 ;
if ( key = = ' h ' ) {
if ( do_hex_dump ) {
do_hex_dump = do_pkt_dump = 0 ;
} else if ( do_pkt_dump ) {
do_hex_dump = 1 ;
} else
do_pkt_dump = 1 ;
av_log_set_level ( AV_LOG_DEBUG ) ;
}
2011-09-01 19:03:39 +02:00
# if CONFIG_AVFILTER
2011-08-28 20:47:06 +02:00
if ( key = = ' c ' | | key = = ' C ' ) {
2011-09-24 13:24:09 +02:00
char buf [ 4096 ] , target [ 64 ] , command [ 256 ] , arg [ 256 ] = { 0 } ;
double time ;
2011-09-24 13:57:26 +02:00
int k , n = 0 ;
2011-08-29 00:07:30 +02:00
fprintf ( stderr , " \n Enter command: <target> <time> <command>[ <argument>] \n " ) ;
2011-09-24 13:24:09 +02:00
i = 0 ;
while ( ( k = read_key ( ) ) ! = ' \n ' & & k ! = ' \r ' & & i < sizeof ( buf ) - 1 )
if ( k > 0 )
buf [ i + + ] = k ;
buf [ i ] = 0 ;
2011-09-24 13:57:26 +02:00
if ( k > 0 & &
( n = sscanf ( buf , " %63[^ ] %lf %255[^ ] %255[^ \n ] " , target , & time , command , arg ) ) > = 3 ) {
av_log ( NULL , AV_LOG_DEBUG , " Processing command target:%s time:%f command:%s arg:%s " ,
target , time , command , arg ) ;
2011-09-24 13:24:09 +02:00
for ( i = 0 ; i < nb_output_streams ; i + + ) {
2011-08-30 15:03:53 +02:00
ost = & output_streams [ i ] ;
2011-09-24 13:24:09 +02:00
if ( ost - > graph ) {
if ( time < 0 ) {
ret = avfilter_graph_send_command ( ost - > graph , target , command , arg , buf , sizeof ( buf ) ,
key = = ' c ' ? AVFILTER_CMD_FLAG_ONE : 0 ) ;
fprintf ( stderr , " Command reply for stream %d: ret:%d res:%s \n " , i , ret , buf ) ;
} else {
ret = avfilter_graph_queue_command ( ost - > graph , target , command , arg , 0 , time ) ;
2011-08-29 00:07:30 +02:00
}
2011-08-28 20:47:06 +02:00
}
}
2011-09-24 13:24:09 +02:00
} else {
2011-09-24 13:57:26 +02:00
av_log ( NULL , AV_LOG_ERROR ,
" Parse error, at least 3 arguments were expected, "
" only %d given in string '%s' \n " , n , buf ) ;
2011-08-28 20:47:06 +02:00
}
}
2011-09-01 19:03:39 +02:00
# endif
2011-05-15 01:39:04 +02:00
if ( key = = ' d ' | | key = = ' D ' ) {
int debug = 0 ;
if ( key = = ' D ' ) {
2011-05-26 03:00:37 +02:00
debug = input_streams [ 0 ] . st - > codec - > debug < < 1 ;
2011-05-15 01:39:04 +02:00
if ( ! debug ) debug = 1 ;
while ( debug & ( FF_DEBUG_DCT_COEFF | FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE ) ) //unsupported, would just crash
debug + = debug ;
} else
2011-11-11 04:05:25 +01:00
if ( scanf ( " %d " , & debug ) ! = 1 )
fprintf ( stderr , " error parsing debug value \n " ) ;
2011-05-26 03:00:37 +02:00
for ( i = 0 ; i < nb_input_streams ; i + + ) {
input_streams [ i ] . st - > codec - > debug = debug ;
2011-05-15 01:39:04 +02:00
}
2011-08-30 15:03:53 +02:00
for ( i = 0 ; i < nb_output_streams ; i + + ) {
ost = & output_streams [ i ] ;
2011-05-15 01:39:04 +02:00
ost - > st - > codec - > debug = debug ;
}
if ( debug ) av_log_set_level ( AV_LOG_DEBUG ) ;
fprintf ( stderr , " debug=%d \n " , debug ) ;
}
2011-05-14 15:51:47 +02:00
if ( key = = ' ? ' ) {
fprintf ( stderr , " key function \n "
" ? show this help \n "
" + increase verbosity \n "
" - decrease verbosity \n "
2011-08-28 20:47:06 +02:00
" c Send command to filtergraph \n "
2011-05-15 01:39:04 +02:00
" D cycle through available debug modes \n "
2011-05-14 15:51:47 +02:00
" h dump packets/hex press to cycle through the 3 states \n "
" q quit \n "
" s Show QP histogram \n "
) ;
}
2002-05-30 04:38:57 +02:00
}
2001-09-25 01:22:25 +02:00
2002-10-21 19:42:47 +02:00
/* select the stream that we must read now by looking at the
smallest output pts */
2001-07-22 16:37:44 +02:00
file_index = - 1 ;
2011-08-30 15:03:53 +02:00
for ( i = 0 ; i < nb_output_streams ; i + + ) {
2011-08-30 15:58:26 +02:00
OutputFile * of ;
2011-08-30 04:45:46 +02:00
int64_t ipts ;
double opts ;
2011-08-30 15:03:53 +02:00
ost = & output_streams [ i ] ;
2011-08-30 15:58:26 +02:00
of = & output_files [ ost - > file_index ] ;
2011-08-30 14:19:39 +02:00
os = output_files [ ost - > file_index ] . ctx ;
2011-05-22 22:12:35 +02:00
ist = & input_streams [ ost - > source_index ] ;
2011-08-30 15:58:26 +02:00
if ( ost - > is_past_recording_time | | no_packet [ ist - > file_index ] | |
( os - > pb & & avio_tell ( os - > pb ) > = of - > limit_filesize ) )
2009-03-03 20:50:04 +01:00
continue ;
2011-08-30 15:59:56 +02:00
opts = ost - > st - > pts . val * av_q2d ( ost - > st - > time_base ) ;
2011-08-30 04:45:46 +02:00
ipts = ist - > pts ;
2011-12-30 03:46:24 +01:00
if ( ! input_files [ ist - > file_index ] . eof_reached ) {
if ( ipts < ipts_min ) {
2004-06-30 00:56:54 +02:00
ipts_min = ipts ;
2011-12-30 03:46:24 +01:00
if ( input_sync )
file_index = ist - > file_index ;
2004-06-30 00:56:54 +02:00
}
2011-12-30 03:46:24 +01:00
if ( opts < opts_min ) {
2004-06-30 00:56:54 +02:00
opts_min = opts ;
2011-12-30 03:46:24 +01:00
if ( ! input_sync ) file_index = ist - > file_index ;
2004-06-30 00:56:54 +02:00
}
2001-07-22 16:37:44 +02:00
}
2011-09-05 22:10:26 +02:00
if ( ost - > frame_number > = ost - > max_frames ) {
int j ;
2011-09-25 23:30:25 +02:00
for ( j = 0 ; j < of - > ctx - > nb_streams ; j + + )
output_streams [ of - > ost_index + j ] . is_past_recording_time = 1 ;
2011-09-05 22:10:26 +02:00
continue ;
2004-11-30 17:03:29 +01:00
}
2001-07-22 16:37:44 +02:00
}
/* if none, if is finished */
2002-05-09 03:06:59 +02:00
if ( file_index < 0 ) {
2011-12-30 03:46:24 +01:00
if ( no_packet_count ) {
no_packet_count = 0 ;
2011-08-30 15:08:02 +02:00
memset ( no_packet , 0 , nb_input_files ) ;
2009-03-03 21:24:58 +01:00
usleep ( 10000 ) ;
2009-03-03 20:50:04 +01:00
continue ;
}
2001-07-22 16:37:44 +02:00
break ;
2002-10-21 19:42:47 +02:00
}
2003-11-10 19:54:17 +01:00
/* read a frame from it and output it in the fifo */
2011-12-30 03:46:24 +01:00
is = input_files [ file_index ] . ctx ;
ret = av_read_frame ( is , & pkt ) ;
if ( ret = = AVERROR ( EAGAIN ) ) {
no_packet [ file_index ] = 1 ;
2009-03-03 20:50:04 +01:00
no_packet_count + + ;
2009-01-22 13:04:01 +01:00
continue ;
2009-03-03 20:50:04 +01:00
}
2009-01-22 13:04:01 +01:00
if ( ret < 0 ) {
2011-05-22 22:12:35 +02:00
input_files [ file_index ] . eof_reached = 1 ;
2007-07-19 02:44:47 +02:00
if ( opt_shortest )
break ;
else
continue ;
2001-07-22 16:37:44 +02:00
}
2004-01-22 20:48:28 +01:00
2011-12-30 03:46:24 +01:00
no_packet_count = 0 ;
2011-08-30 15:08:02 +02:00
memset ( no_packet , 0 , nb_input_files ) ;
2009-03-03 20:50:04 +01:00
2003-11-10 19:54:17 +01:00
if ( do_pkt_dump ) {
2011-02-24 09:08:07 +01:00
av_pkt_dump_log2 ( NULL , AV_LOG_DEBUG , & pkt , do_hex_dump ,
is - > streams [ pkt . stream_index ] ) ;
2003-01-11 06:05:47 +01:00
}
2002-05-20 18:32:49 +02:00
/* the following test is needed in case new streams appear
dynamically in stream : we ignore them */
2011-08-04 11:06:43 +02:00
if ( pkt . stream_index > = input_files [ file_index ] . nb_streams )
2002-05-26 00:25:13 +02:00
goto discard_packet ;
2011-05-22 22:12:35 +02:00
ist_index = input_files [ file_index ] . ist_index + pkt . stream_index ;
ist = & input_streams [ ist_index ] ;
2002-05-26 00:25:13 +02:00
if ( ist - > discard )
goto discard_packet ;
2001-07-22 16:37:44 +02:00
2007-08-03 21:21:50 +02:00
if ( pkt . dts ! = AV_NOPTS_VALUE )
2011-06-23 19:30:15 +02:00
pkt . dts + = av_rescale_q ( input_files [ ist - > file_index ] . ts_offset , AV_TIME_BASE_Q , ist - > st - > time_base ) ;
2007-08-03 21:21:50 +02:00
if ( pkt . pts ! = AV_NOPTS_VALUE )
2011-06-23 19:30:15 +02:00
pkt . pts + = av_rescale_q ( input_files [ ist - > file_index ] . ts_offset , AV_TIME_BASE_Q , ist - > st - > time_base ) ;
2007-08-03 21:21:50 +02:00
2011-12-30 03:46:24 +01:00
if ( pkt . pts ! = AV_NOPTS_VALUE )
2011-09-05 22:10:26 +02:00
pkt . pts * = ist - > ts_scale ;
2011-12-30 03:46:24 +01:00
if ( pkt . dts ! = AV_NOPTS_VALUE )
2011-09-05 22:10:26 +02:00
pkt . dts * = ist - > ts_scale ;
2008-07-14 00:55:52 +02:00
2011-12-30 03:46:24 +01:00
//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);
2008-10-09 20:28:43 +02:00
if ( pkt . dts ! = AV_NOPTS_VALUE & & ist - > next_pts ! = AV_NOPTS_VALUE
& & ( is - > iformat - > flags & AVFMT_TS_DISCONT ) ) {
2011-12-30 03:46:24 +01:00
int64_t pkt_dts = av_rescale_q ( pkt . dts , ist - > st - > time_base , AV_TIME_BASE_Q ) ;
int64_t delta = pkt_dts - ist - > next_pts ;
2011-08-16 15:49:17 +02:00
if ( ( delta < - 1LL * dts_delta_threshold * AV_TIME_BASE | |
( delta > 1LL * dts_delta_threshold * AV_TIME_BASE & &
ist - > st - > codec - > codec_type ! = AVMEDIA_TYPE_SUBTITLE ) | |
pkt_dts + 1 < ist - > pts ) & & ! copy_ts ) {
2011-06-23 19:30:15 +02:00
input_files [ ist - > file_index ] . ts_offset - = delta ;
2011-12-30 03:46:24 +01:00
av_log ( NULL , AV_LOG_DEBUG ,
" timestamp discontinuity % " PRId64 " , new offset= % " PRId64 " \n " ,
2011-09-27 02:14:37 +02:00
delta , input_files [ ist - > file_index ] . ts_offset ) ;
2007-08-03 21:21:50 +02:00
pkt . dts - = av_rescale_q ( delta , AV_TIME_BASE_Q , ist - > st - > time_base ) ;
2011-12-30 03:46:24 +01:00
if ( pkt . pts ! = AV_NOPTS_VALUE )
2007-08-03 21:21:50 +02:00
pkt . pts - = av_rescale_q ( delta , AV_TIME_BASE_Q , ist - > st - > time_base ) ;
2004-06-12 05:41:36 +02:00
}
}
2011-12-30 03:46:24 +01:00
// fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size);
2011-11-24 02:08:21 +01:00
if ( output_packet ( ist , output_streams , nb_output_streams , & pkt ) < 0 ) {
2004-04-11 15:50:42 +02:00
2011-11-07 02:41:01 +01:00
av_log ( NULL , AV_LOG_ERROR , " Error while decoding stream #%d:%d \n " ,
2011-09-27 02:14:37 +02:00
ist - > file_index , ist - > st - > index ) ;
2008-09-05 01:23:44 +02:00
if ( exit_on_error )
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2003-12-15 15:43:44 +01:00
av_free_packet ( & pkt ) ;
2011-08-30 16:39:05 +02:00
continue ;
2003-10-14 16:36:58 +02:00
}
2005-06-03 16:31:45 +02:00
2002-05-26 00:25:13 +02:00
discard_packet :
2001-07-22 16:37:44 +02:00
av_free_packet ( & pkt ) ;
2005-12-17 19:14:38 +01:00
2002-10-21 19:42:47 +02:00
/* dump report by using the output first video and audio streams */
2011-10-08 17:32:06 +02:00
print_report ( output_files , output_streams , nb_output_streams , 0 , timer_start , cur_time ) ;
2001-07-22 16:37:44 +02:00
}
2003-12-15 15:43:44 +01:00
/* at the end of stream, we must flush the decoder buffers */
2011-05-22 22:12:35 +02:00
for ( i = 0 ; i < nb_input_streams ; i + + ) {
ist = & input_streams [ i ] ;
2003-12-15 15:43:44 +01:00
if ( ist - > decoding_needed ) {
2011-11-24 02:08:21 +01:00
output_packet ( ist , output_streams , nb_output_streams , NULL ) ;
2003-12-15 15:43:44 +01:00
}
}
2011-08-30 16:00:47 +02:00
flush_encoders ( output_streams , nb_output_streams ) ;
2003-12-15 15:43:44 +01:00
2001-09-25 01:22:25 +02:00
term_exit ( ) ;
2001-07-22 16:37:44 +02:00
2004-03-05 23:51:22 +01:00
/* write the trailer if needed and close file */
2011-12-30 03:46:24 +01:00
for ( i = 0 ; i < nb_output_files ; i + + ) {
2011-08-30 14:19:39 +02:00
os = output_files [ i ] . ctx ;
2004-03-05 23:51:22 +01:00
av_write_trailer ( os ) ;
}
2004-04-15 18:34:38 +02:00
/* dump report by using the first video and audio streams */
2011-10-08 17:32:06 +02:00
print_report ( output_files , output_streams , nb_output_streams , 1 , timer_start , av_gettime ( ) ) ;
2004-04-15 18:34:38 +02:00
2001-07-22 16:37:44 +02:00
/* close each encoder */
2011-08-30 15:03:53 +02:00
for ( i = 0 ; i < nb_output_streams ; i + + ) {
ost = & output_streams [ i ] ;
2001-07-22 16:37:44 +02:00
if ( ost - > encoding_needed ) {
2005-07-18 00:24:36 +02:00
av_freep ( & ost - > st - > codec - > stats_in ) ;
avcodec_close ( ost - > st - > codec ) ;
2001-07-22 16:37:44 +02:00
}
2011-02-14 23:02:10 +01:00
# if CONFIG_AVFILTER
avfilter_graph_free ( & ost - > graph ) ;
# endif
2001-07-22 16:37:44 +02:00
}
2005-12-17 19:14:38 +01:00
2001-07-22 16:37:44 +02:00
/* close each decoder */
2011-05-22 22:12:35 +02:00
for ( i = 0 ; i < nb_input_streams ; i + + ) {
ist = & input_streams [ i ] ;
2001-07-22 16:37:44 +02:00
if ( ist - > decoding_needed ) {
2005-07-18 00:24:36 +02:00
avcodec_close ( ist - > st - > codec ) ;
2001-07-22 16:37:44 +02:00
}
}
/* finished ! */
2009-03-11 07:13:14 +01:00
ret = 0 ;
2005-12-17 19:14:38 +01:00
2009-03-11 07:06:18 +01:00
fail :
2005-01-12 19:12:13 +01:00
av_freep ( & bit_buffer ) ;
2011-08-30 15:08:02 +02:00
av_freep ( & no_packet ) ;
2001-08-13 23:43:02 +02:00
2011-08-30 15:03:53 +02:00
if ( output_streams ) {
for ( i = 0 ; i < nb_output_streams ; i + + ) {
ost = & output_streams [ i ] ;
2001-07-22 16:37:44 +02:00
if ( ost ) {
2011-10-26 02:09:31 +02:00
if ( ost - > stream_copy )
2010-06-08 21:27:29 +02:00
av_freep ( & ost - > st - > codec - > extradata ) ;
2002-10-10 19:09:01 +02:00
if ( ost - > logfile ) {
fclose ( ost - > logfile ) ;
ost - > logfile = NULL ;
}
2009-03-08 15:16:55 +01:00
av_fifo_free ( ost - > fifo ) ; /* works even if fifo is not
2006-09-21 09:31:53 +02:00
initialized but set to zero */
2010-11-13 14:57:49 +01:00
av_freep ( & ost - > st - > codec - > subtitle_header ) ;
2011-05-06 11:30:27 +02:00
av_free ( ost - > resample_frame . data [ 0 ] ) ;
2010-10-18 23:47:15 +02:00
av_free ( ost - > forced_kf_pts ) ;
2001-07-22 16:37:44 +02:00
if ( ost - > video_resample )
2006-08-02 13:50:38 +02:00
sws_freeContext ( ost - > img_resample_ctx ) ;
2011-09-19 06:13:30 +02:00
swr_free ( & ost - > swr ) ;
2011-05-25 17:29:25 +02:00
av_dict_free ( & ost - > opts ) ;
2001-07-22 16:37:44 +02:00
}
}
}
return ret ;
}
2010-10-18 15:34:46 +02:00
static int opt_frame_crop ( const char * opt , const char * arg )
2002-09-01 09:19:38 +02:00
{
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Option '%s' has been removed, use the crop filter instead \n " , opt ) ;
2010-10-18 15:34:46 +02:00
return AVERROR ( EINVAL ) ;
2002-09-01 09:19:38 +02:00
}
2011-09-12 11:44:14 +02:00
static int opt_pad ( const char * opt , const char * arg )
{
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Option '%s' has been removed, use the pad filter instead \n " , opt ) ;
2010-07-04 22:59:02 +02:00
return - 1 ;
2004-04-08 20:54:40 +02:00
}
2011-09-11 23:35:35 +02:00
static double parse_frame_aspect_ratio ( const char * arg )
2003-04-29 21:46:08 +02:00
{
int x = 0 , y = 0 ;
double ar = 0 ;
const char * p ;
2008-02-02 01:54:37 +01:00
char * end ;
2005-12-17 19:14:38 +01:00
2003-04-29 21:46:08 +02:00
p = strchr ( arg , ' : ' ) ;
if ( p ) {
2008-02-02 01:54:37 +01:00
x = strtol ( arg , & end , 10 ) ;
if ( end = = p )
2011-12-30 03:46:24 +01:00
y = strtol ( end + 1 , & end , 10 ) ;
2005-12-22 02:10:11 +01:00
if ( x > 0 & & y > 0 )
ar = ( double ) x / ( double ) y ;
2003-04-29 21:46:08 +02:00
} else
2008-02-02 01:54:37 +01:00
ar = strtod ( arg , NULL ) ;
2003-04-29 21:46:08 +02:00
if ( ! ar ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Incorrect aspect ratio specification. \n " ) ;
2011-08-29 07:03:24 +02:00
exit_program ( 1 ) ;
2008-07-31 15:11:07 +02:00
}
2011-09-11 23:35:35 +02:00
return ar ;
2001-07-22 16:37:44 +02:00
}
2011-04-11 13:16:07 +02:00
static int opt_video_channel ( const char * opt , const char * arg )
2003-01-23 19:44:26 +01:00
{
2011-06-15 07:34:12 +02:00
av_log ( NULL , AV_LOG_WARNING , " This option is deprecated, use -channel. \n " ) ;
2011-08-01 00:36:52 +02:00
return opt_default ( " channel " , arg ) ;
2003-01-23 19:44:26 +01:00
}
2011-05-24 18:14:42 +02:00
static int opt_video_standard ( const char * opt , const char * arg )
2003-06-25 12:21:45 +02:00
{
2011-06-15 07:34:12 +02:00
av_log ( NULL , AV_LOG_WARNING , " This option is deprecated, use -standard. \n " ) ;
2011-08-01 00:36:52 +02:00
return opt_default ( " standard " , arg ) ;
2003-06-25 12:21:45 +02:00
}
2011-09-05 22:10:26 +02:00
static int opt_audio_codec ( OptionsContext * o , const char * opt , const char * arg )
2001-07-22 16:37:44 +02:00
{
2011-09-05 22:10:26 +02:00
audio_codec_name = arg ;
return parse_option ( o , " codec:a " , arg , options ) ;
2001-07-22 16:37:44 +02:00
}
2011-09-05 22:10:26 +02:00
static int opt_video_codec ( OptionsContext * o , const char * opt , const char * arg )
2011-08-30 04:06:57 +02:00
{
2011-09-05 22:10:26 +02:00
video_codec_name = arg ;
return parse_option ( o , " codec:v " , arg , options ) ;
2011-08-30 04:06:57 +02:00
}
2011-09-05 22:10:26 +02:00
static int opt_subtitle_codec ( OptionsContext * o , const char * opt , const char * arg )
2011-08-30 04:06:57 +02:00
{
2011-09-05 22:10:26 +02:00
subtitle_codec_name = arg ;
return parse_option ( o , " codec:s " , arg , options ) ;
2011-08-30 04:06:57 +02:00
}
2011-09-05 22:10:26 +02:00
static int opt_data_codec ( OptionsContext * o , const char * opt , const char * arg )
2011-08-30 04:06:57 +02:00
{
2011-09-05 22:10:26 +02:00
return parse_option ( o , " codec:d " , arg , options ) ;
2011-08-30 04:06:57 +02:00
}
2011-09-05 02:04:27 +02:00
static int opt_map ( OptionsContext * o , const char * opt , const char * arg )
2001-07-22 16:37:44 +02:00
{
2011-08-30 04:06:24 +02:00
StreamMap * m = NULL ;
int i , negative = 0 , file_idx ;
2012-01-03 00:28:06 +01:00
int sync_file_idx = - 1 , sync_stream_idx = 0 ;
2011-08-30 04:06:24 +02:00
char * p , * sync ;
char * map ;
2001-07-22 16:37:44 +02:00
2011-08-30 04:06:24 +02:00
if ( * arg = = ' - ' ) {
negative = 1 ;
arg + + ;
}
map = av_strdup ( arg ) ;
2001-07-22 16:37:44 +02:00
2011-08-30 04:06:24 +02:00
/* parse sync stream first, just pick first matching stream */
if ( sync = strchr ( map , ' , ' ) ) {
* sync = 0 ;
sync_file_idx = strtol ( sync + 1 , & sync , 0 ) ;
if ( sync_file_idx > = nb_input_files | | sync_file_idx < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Invalid sync file index: %d. \n " , sync_file_idx ) ;
2011-08-30 04:06:24 +02:00
exit_program ( 1 ) ;
}
if ( * sync )
sync + + ;
2011-08-30 16:43:11 +02:00
for ( i = 0 ; i < input_files [ sync_file_idx ] . nb_streams ; i + + )
2011-08-30 04:06:24 +02:00
if ( check_stream_specifier ( input_files [ sync_file_idx ] . ctx ,
input_files [ sync_file_idx ] . ctx - > streams [ i ] , sync ) = = 1 ) {
sync_stream_idx = i ;
break ;
}
2011-08-30 16:43:11 +02:00
if ( i = = input_files [ sync_file_idx ] . nb_streams ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Sync stream specification in map %s does not "
2011-08-30 04:06:24 +02:00
" match any streams. \n " , arg ) ;
exit_program ( 1 ) ;
}
}
2002-05-12 01:27:14 +02:00
2011-08-30 04:06:24 +02:00
file_idx = strtol ( map , & p , 0 ) ;
if ( file_idx > = nb_input_files | | file_idx < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Invalid input file index: %d. \n " , file_idx ) ;
2011-08-30 04:06:24 +02:00
exit_program ( 1 ) ;
2005-05-26 10:59:05 +02:00
}
2011-08-30 04:06:24 +02:00
if ( negative )
/* disable some already defined maps */
2011-09-05 02:04:27 +02:00
for ( i = 0 ; i < o - > nb_stream_maps ; i + + ) {
m = & o - > stream_maps [ i ] ;
2011-11-04 01:44:06 +01:00
if ( file_idx = = m - > file_index & &
check_stream_specifier ( input_files [ m - > file_index ] . ctx ,
2011-08-30 04:06:24 +02:00
input_files [ m - > file_index ] . ctx - > streams [ m - > stream_index ] ,
* p = = ' : ' ? p + 1 : p ) > 0 )
m - > disabled = 1 ;
}
else
2011-08-30 16:43:11 +02:00
for ( i = 0 ; i < input_files [ file_idx ] . nb_streams ; i + + ) {
2011-08-30 04:06:24 +02:00
if ( check_stream_specifier ( input_files [ file_idx ] . ctx , input_files [ file_idx ] . ctx - > streams [ i ] ,
* p = = ' : ' ? p + 1 : p ) < = 0 )
continue ;
2011-09-05 02:04:27 +02:00
o - > stream_maps = grow_array ( o - > stream_maps , sizeof ( * o - > stream_maps ) ,
& o - > nb_stream_maps , o - > nb_stream_maps + 1 ) ;
m = & o - > stream_maps [ o - > nb_stream_maps - 1 ] ;
2011-08-30 04:06:24 +02:00
m - > file_index = file_idx ;
m - > stream_index = i ;
if ( sync_file_idx > = 0 ) {
m - > sync_file_index = sync_file_idx ;
m - > sync_stream_index = sync_stream_idx ;
} else {
m - > sync_file_index = file_idx ;
m - > sync_stream_index = i ;
}
}
if ( ! m ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Stream map '%s' matches no streams. \n " , arg ) ;
2011-08-30 04:06:24 +02:00
exit_program ( 1 ) ;
}
av_freep ( & map ) ;
2011-05-24 18:14:42 +02:00
return 0 ;
2001-07-22 16:37:44 +02:00
}
2011-11-04 01:44:06 +01:00
static int opt_attach ( OptionsContext * o , const char * opt , const char * arg )
2011-04-14 13:32:36 +02:00
{
2011-11-04 01:44:06 +01:00
o - > attachments = grow_array ( o - > attachments , sizeof ( * o - > attachments ) ,
& o - > nb_attachments , o - > nb_attachments + 1 ) ;
o - > attachments [ o - > nb_attachments - 1 ] = arg ;
return 0 ;
2011-04-14 13:32:36 +02:00
}
2011-11-04 18:54:01 +01:00
static int opt_map_channel ( OptionsContext * o , const char * opt , const char * arg )
{
int n ;
AVStream * st ;
AudioChannelMap * m ;
o - > audio_channel_maps =
grow_array ( o - > audio_channel_maps , sizeof ( * o - > audio_channel_maps ) ,
& o - > nb_audio_channel_maps , o - > nb_audio_channel_maps + 1 ) ;
m = & o - > audio_channel_maps [ o - > nb_audio_channel_maps - 1 ] ;
/* muted channel syntax */
n = sscanf ( arg , " %d:%d.%d " , & m - > channel_idx , & m - > ofile_idx , & m - > ostream_idx ) ;
if ( ( n = = 1 | | n = = 3 ) & & m - > channel_idx = = - 1 ) {
m - > file_idx = m - > stream_idx = - 1 ;
if ( n = = 1 )
m - > ofile_idx = m - > ostream_idx = - 1 ;
return 0 ;
}
/* normal syntax */
n = sscanf ( arg , " %d.%d.%d:%d.%d " ,
& m - > file_idx , & m - > stream_idx , & m - > channel_idx ,
& m - > ofile_idx , & m - > ostream_idx ) ;
if ( n ! = 3 & & n ! = 5 ) {
av_log ( NULL , AV_LOG_FATAL , " Syntax error, mapchan usage: "
" [file.stream.channel|-1][:syncfile:syncstream] \n " ) ;
exit_program ( 1 ) ;
}
if ( n ! = 5 ) // only file.stream.channel specified
m - > ofile_idx = m - > ostream_idx = - 1 ;
/* check input */
if ( m - > file_idx < 0 | | m - > file_idx > = nb_input_files ) {
av_log ( NULL , AV_LOG_FATAL , " mapchan: invalid input file index: %d \n " ,
m - > file_idx ) ;
exit_program ( 1 ) ;
}
if ( m - > stream_idx < 0 | |
m - > stream_idx > = input_files [ m - > file_idx ] . nb_streams ) {
av_log ( NULL , AV_LOG_FATAL , " mapchan: invalid input file stream index #%d.%d \n " ,
m - > file_idx , m - > stream_idx ) ;
exit_program ( 1 ) ;
}
st = input_files [ m - > file_idx ] . ctx - > streams [ m - > stream_idx ] ;
if ( st - > codec - > codec_type ! = AVMEDIA_TYPE_AUDIO ) {
av_log ( NULL , AV_LOG_FATAL , " mapchan: stream #%d.%d is not an audio stream. \n " ,
m - > file_idx , m - > stream_idx ) ;
exit_program ( 1 ) ;
}
if ( m - > channel_idx < 0 | | m - > channel_idx > = st - > codec - > channels ) {
av_log ( NULL , AV_LOG_FATAL , " mapchan: invalid audio channel #%d.%d.%d \n " ,
m - > file_idx , m - > stream_idx , m - > channel_idx ) ;
exit_program ( 1 ) ;
}
return 0 ;
}
2011-12-17 01:36:59 +01:00
/**
* Parse a metadata specifier in arg .
* @ param type metadata type is written here - - g ( lobal ) / s ( tream ) / c ( hapter ) / p ( rogram )
* @ param index for type c / p , chapter / program index is written here
* @ param stream_spec for type s , the stream specifier is written here
*/
static void parse_meta_type ( char * arg , char * type , int * index , const char * * stream_spec )
2010-11-02 07:01:28 +01:00
{
2011-09-05 22:10:26 +02:00
if ( * arg ) {
* type = * arg ;
2010-11-02 07:01:28 +01:00
switch ( * arg ) {
case ' g ' :
break ;
case ' s ' :
2011-12-17 01:36:59 +01:00
if ( * ( + + arg ) & & * arg ! = ' : ' ) {
av_log ( NULL , AV_LOG_FATAL , " Invalid metadata specifier %s. \n " , arg ) ;
exit_program ( 1 ) ;
}
* stream_spec = * arg = = ' : ' ? arg + 1 : " " ;
break ;
2010-11-02 07:01:28 +01:00
case ' c ' :
case ' p ' :
2011-08-30 01:30:11 +02:00
if ( * ( + + arg ) = = ' : ' )
* index = strtol ( + + arg , NULL , 0 ) ;
2010-11-02 07:01:28 +01:00
break ;
default :
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Invalid metadata type %c. \n " , * arg ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2010-11-02 07:01:28 +01:00
}
} else
* type = ' g ' ;
}
2011-12-17 01:36:59 +01:00
static int copy_metadata ( char * outspec , char * inspec , AVFormatContext * oc , AVFormatContext * ic , OptionsContext * o )
2004-07-21 03:35:32 +02:00
{
2011-12-17 01:36:59 +01:00
AVDictionary * * meta_in = NULL ;
2012-01-03 00:28:06 +01:00
AVDictionary * * meta_out = NULL ;
2011-12-17 01:36:59 +01:00
int i , ret = 0 ;
char type_in , type_out ;
const char * istream_spec = NULL , * ostream_spec = NULL ;
int idx_in = 0 , idx_out = 0 ;
2004-07-21 03:35:32 +02:00
2011-12-17 01:36:59 +01:00
parse_meta_type ( inspec , & type_in , & idx_in , & istream_spec ) ;
parse_meta_type ( outspec , & type_out , & idx_out , & ostream_spec ) ;
2010-11-02 07:12:54 +01:00
2011-12-17 01:36:59 +01:00
if ( type_in = = ' g ' | | type_out = = ' g ' )
2011-09-05 22:10:26 +02:00
o - > metadata_global_manual = 1 ;
2011-12-17 01:36:59 +01:00
if ( type_in = = ' s ' | | type_out = = ' s ' )
2011-09-05 22:10:26 +02:00
o - > metadata_streams_manual = 1 ;
2011-12-17 01:36:59 +01:00
if ( type_in = = ' c ' | | type_out = = ' c ' )
2011-09-05 22:10:26 +02:00
o - > metadata_chapters_manual = 1 ;
2011-05-24 18:14:42 +02:00
2011-12-17 01:36:59 +01:00
# define METADATA_CHECK_INDEX(index, nb_elems, desc)\
if ( ( index ) < 0 | | ( index ) > = ( nb_elems ) ) { \
av_log ( NULL , AV_LOG_FATAL , " Invalid %s index %d while processing metadata maps. \n " , \
( desc ) , ( index ) ) ; \
exit_program ( 1 ) ; \
}
2004-07-21 03:35:32 +02:00
2011-12-17 01:36:59 +01:00
# define SET_DICT(type, meta, context, index)\
switch ( type ) { \
case ' g ' : \
meta = & context - > metadata ; \
break ; \
case ' c ' : \
METADATA_CHECK_INDEX ( index , context - > nb_chapters , " chapter " ) \
meta = & context - > chapters [ index ] - > metadata ; \
break ; \
case ' p ' : \
METADATA_CHECK_INDEX ( index , context - > nb_programs , " program " ) \
meta = & context - > programs [ index ] - > metadata ; \
break ; \
} \
SET_DICT ( type_in , meta_in , ic , idx_in ) ;
SET_DICT ( type_out , meta_out , oc , idx_out ) ;
/* for input streams choose first matching stream */
if ( type_in = = ' s ' ) {
for ( i = 0 ; i < ic - > nb_streams ; i + + ) {
if ( ( ret = check_stream_specifier ( ic , ic - > streams [ i ] , istream_spec ) ) > 0 ) {
meta_in = & ic - > streams [ i ] - > metadata ;
break ;
} else if ( ret < 0 )
exit_program ( 1 ) ;
}
if ( ! meta_in ) {
av_log ( NULL , AV_LOG_FATAL , " Stream specifier %s does not match any streams. \n " , istream_spec ) ;
exit_program ( 1 ) ;
}
}
2004-07-21 03:35:32 +02:00
2011-12-17 01:36:59 +01:00
if ( type_out = = ' s ' ) {
for ( i = 0 ; i < oc - > nb_streams ; i + + ) {
if ( ( ret = check_stream_specifier ( oc , oc - > streams [ i ] , ostream_spec ) ) > 0 ) {
meta_out = & oc - > streams [ i ] - > metadata ;
av_dict_copy ( meta_out , * meta_in , AV_DICT_DONT_OVERWRITE ) ;
} else if ( ret < 0 )
exit_program ( 1 ) ;
}
} else
av_dict_copy ( meta_out , * meta_in , AV_DICT_DONT_OVERWRITE ) ;
2011-05-28 01:53:00 +02:00
return 0 ;
2008-07-14 00:55:52 +02:00
}
2011-09-05 22:10:26 +02:00
static int opt_recording_timestamp ( OptionsContext * o , const char * opt , const char * arg )
2004-04-06 08:31:12 +02:00
{
2011-07-07 11:25:03 +02:00
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 ) ;
2011-09-05 22:10:26 +02:00
parse_option ( o , " metadata " , buf , options ) ;
2011-07-07 11:25:03 +02:00
av_log ( NULL , AV_LOG_WARNING , " %s is deprecated, set the 'creation_time' metadata "
" tag instead. \n " , opt ) ;
2008-03-22 16:12:04 +01:00
return 0 ;
2004-04-06 08:31:12 +02:00
}
2011-10-26 02:09:31 +02:00
static AVCodec * find_codec_or_die ( const char * name , enum AVMediaType type , int encoder )
2011-08-30 04:19:26 +02:00
{
const char * codec_string = encoder ? " encoder " : " decoder " ;
AVCodec * codec ;
codec = encoder ?
avcodec_find_encoder_by_name ( name ) :
avcodec_find_decoder_by_name ( name ) ;
2011-12-30 03:46:24 +01:00
if ( ! codec ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Unknown %s '%s' \n " , codec_string , name ) ;
2011-08-30 04:19:26 +02:00
exit_program ( 1 ) ;
}
2011-12-30 03:46:24 +01:00
if ( codec - > type ! = type ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Invalid %s type '%s' \n " , codec_string , name ) ;
2011-08-30 04:19:26 +02:00
exit_program ( 1 ) ;
}
2011-10-26 02:09:31 +02:00
return codec ;
2011-08-30 04:19:26 +02:00
}
2011-10-26 02:09:31 +02:00
static AVCodec * choose_decoder ( OptionsContext * o , AVFormatContext * s , AVStream * st )
2011-08-30 04:19:26 +02:00
{
char * codec_name = NULL ;
2011-09-05 22:10:26 +02:00
MATCH_PER_STREAM_OPT ( codec_names , str , codec_name , s , st ) ;
2011-10-26 02:09:31 +02:00
if ( codec_name ) {
AVCodec * codec = find_codec_or_die ( codec_name , st - > codec - > codec_type , 0 ) ;
st - > codec - > codec_id = codec - > id ;
return codec ;
} else
return avcodec_find_decoder ( st - > codec - > codec_id ) ;
2011-08-30 04:19:26 +02:00
}
2007-08-08 16:34:51 +02:00
2011-08-30 14:07:49 +02:00
/**
* Add all the streams from the given input file to the global
* list of input streams .
*/
2011-09-05 22:10:26 +02:00
static void add_input_streams ( OptionsContext * o , AVFormatContext * ic )
2011-08-30 14:07:49 +02:00
{
2012-01-03 02:25:56 +01:00
int i ;
2011-10-16 19:05:11 +02:00
char * next , * codec_tag = NULL ;
2011-08-30 14:07:49 +02:00
for ( i = 0 ; i < ic - > nb_streams ; i + + ) {
AVStream * st = ic - > streams [ i ] ;
AVCodecContext * dec = st - > codec ;
InputStream * ist ;
input_streams = grow_array ( input_streams , sizeof ( * input_streams ) , & nb_input_streams , nb_input_streams + 1 ) ;
ist = & input_streams [ nb_input_streams - 1 ] ;
ist - > st = st ;
ist - > file_index = nb_input_files ;
ist - > discard = 1 ;
2011-11-27 21:17:56 +01:00
ist - > opts = filter_codec_opts ( codec_opts , choose_decoder ( o , ic , st ) , ic , st ) ;
2011-08-30 14:07:49 +02:00
2011-11-07 02:41:01 +01:00
ist - > ts_scale = 1.0 ;
MATCH_PER_STREAM_OPT ( ts_scale , dbl , ist - > ts_scale , ic , st ) ;
2011-08-30 14:07:49 +02:00
2011-10-16 19:05:11 +02:00
MATCH_PER_STREAM_OPT ( codec_tags , str , codec_tag , ic , st ) ;
if ( codec_tag ) {
uint32_t tag = strtol ( codec_tag , & next , 0 ) ;
if ( * next )
tag = AV_RL32 ( codec_tag ) ;
st - > codec - > codec_tag = tag ;
}
2011-10-26 02:09:31 +02:00
ist - > dec = choose_decoder ( o , ic , st ) ;
2011-08-30 14:07:49 +02:00
switch ( dec - > codec_type ) {
case AVMEDIA_TYPE_AUDIO :
2011-12-30 03:46:24 +01:00
if ( ! ist - > dec )
2011-08-30 14:07:49 +02:00
ist - > dec = avcodec_find_decoder ( dec - > codec_id ) ;
2011-12-30 03:46:24 +01:00
if ( o - > audio_disable )
st - > discard = AVDISCARD_ALL ;
2011-08-30 14:07:49 +02:00
break ;
case AVMEDIA_TYPE_VIDEO :
if ( ! ist - > dec )
ist - > dec = avcodec_find_decoder ( dec - > codec_id ) ;
if ( dec - > lowres ) {
dec - > flags | = CODEC_FLAG_EMU_EDGE ;
}
2011-09-10 20:52:48 +02:00
if ( o - > video_disable )
2011-12-30 03:46:24 +01:00
st - > discard = AVDISCARD_ALL ;
else if ( video_discard )
st - > discard = video_discard ;
2011-08-30 14:07:49 +02:00
break ;
case AVMEDIA_TYPE_DATA :
2011-12-01 18:02:04 +01:00
if ( o - > data_disable )
st - > discard = AVDISCARD_ALL ;
2011-08-30 14:07:49 +02:00
break ;
case AVMEDIA_TYPE_SUBTITLE :
if ( ! ist - > dec )
ist - > dec = avcodec_find_decoder ( dec - > codec_id ) ;
2011-09-10 20:52:48 +02:00
if ( o - > subtitle_disable )
2011-08-30 14:07:49 +02:00
st - > discard = AVDISCARD_ALL ;
break ;
case AVMEDIA_TYPE_ATTACHMENT :
case AVMEDIA_TYPE_UNKNOWN :
break ;
default :
abort ( ) ;
}
}
}
2011-11-04 01:44:06 +01:00
static void assert_file_overwrite ( const char * filename )
2004-06-12 00:03:16 +02:00
{
2011-11-24 21:42:42 +01:00
if ( ( ! file_overwrite | | no_file_overwrite ) & &
2011-11-04 01:44:06 +01:00
( strchr ( filename , ' : ' ) = = NULL | | filename [ 1 ] = = ' : ' | |
av_strstart ( filename , " file: " , NULL ) ) ) {
if ( avio_check ( filename , 0 ) = = 0 ) {
2011-11-24 21:42:42 +01:00
if ( ! using_stdin & & ( ! no_file_overwrite | | file_overwrite ) ) {
2011-11-04 01:44:06 +01:00
fprintf ( stderr , " File '%s' already exists. Overwrite ? [y/N] " , filename ) ;
fflush ( stderr ) ;
term_exit ( ) ;
2011-12-16 19:43:54 +01:00
signal ( SIGINT , SIG_DFL ) ;
2011-11-04 01:44:06 +01:00
if ( ! read_yesno ( ) ) {
av_log ( 0 , AV_LOG_FATAL , " Not overwriting - exiting \n " ) ;
exit_program ( 1 ) ;
}
term_init ( ) ;
}
else {
av_log ( 0 , AV_LOG_FATAL , " File '%s' already exists. Exiting. \n " , filename ) ;
exit_program ( 1 ) ;
}
}
}
2004-06-12 00:03:16 +02:00
}
2011-11-04 01:44:06 +01:00
static void dump_attachment ( AVStream * st , const char * filename )
2007-08-08 16:34:51 +02:00
{
2011-11-04 01:44:06 +01:00
int ret ;
AVIOContext * out = NULL ;
AVDictionaryEntry * e ;
2007-08-08 16:34:51 +02:00
2011-11-04 01:44:06 +01:00
if ( ! st - > codec - > extradata_size ) {
av_log ( NULL , AV_LOG_WARNING , " No extradata to dump in stream #%d:%d. \n " ,
nb_input_files - 1 , st - > index ) ;
return ;
}
if ( ! * filename & & ( e = av_dict_get ( st - > metadata , " filename " , NULL , 0 ) ) )
filename = e - > value ;
if ( ! * filename ) {
av_log ( NULL , AV_LOG_FATAL , " No filename specified and no 'filename' tag "
" in stream #%d:%d. \n " , nb_input_files - 1 , st - > index ) ;
2011-08-29 07:03:24 +02:00
exit_program ( 1 ) ;
2007-08-08 16:34:51 +02:00
}
2011-11-04 01:44:06 +01:00
assert_file_overwrite ( filename ) ;
2011-11-19 01:55:55 +01:00
if ( ( ret = avio_open2 ( & out , filename , AVIO_FLAG_WRITE , & int_cb , NULL ) ) < 0 ) {
2011-11-04 01:44:06 +01:00
av_log ( NULL , AV_LOG_FATAL , " Could not open file %s for writing. \n " ,
filename ) ;
2011-08-29 07:03:24 +02:00
exit_program ( 1 ) ;
2007-08-08 16:34:51 +02:00
}
2011-11-04 01:44:06 +01:00
avio_write ( out , st - > codec - > extradata , st - > codec - > extradata_size ) ;
avio_flush ( out ) ;
avio_close ( out ) ;
2007-08-08 16:34:51 +02:00
}
2011-09-05 02:04:27 +02:00
static int opt_input_file ( OptionsContext * o , const char * opt , const char * filename )
2001-07-22 16:37:44 +02:00
{
AVFormatContext * ic ;
2009-10-30 10:57:34 +01:00
AVInputFormat * file_iformat = NULL ;
2011-08-30 14:07:49 +02:00
int err , i , ret ;
2004-09-20 17:49:24 +02:00
int64_t timestamp ;
2011-06-09 10:58:23 +02:00
uint8_t buf [ 128 ] ;
2011-05-25 17:29:25 +02:00
AVDictionary * * opts ;
int orig_nb_streams ; // number of streams before avformat_find_stream_info
2001-07-22 16:37:44 +02:00
2011-09-05 02:04:27 +02:00
if ( o - > format ) {
if ( ! ( file_iformat = av_find_input_format ( o - > format ) ) ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Unknown input format: '%s' \n " , o - > format ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2010-03-02 01:01:16 +01:00
}
2009-10-30 10:57:34 +01:00
}
2002-11-19 20:08:56 +01:00
if ( ! strcmp ( filename , " - " ) )
filename = " pipe: " ;
2005-12-17 19:14:38 +01:00
using_stdin | = ! strncmp ( filename , " pipe: " , 5 ) | |
2008-05-29 23:26:30 +02:00
! strcmp ( filename , " /dev/stdin " ) ;
2003-08-29 22:51:10 +02:00
2001-07-22 16:37:44 +02:00
/* get default parameters from command line */
2009-02-08 09:27:26 +01:00
ic = avformat_alloc_context ( ) ;
2009-09-12 19:22:56 +02:00
if ( ! ic ) {
print_error ( filename , AVERROR ( ENOMEM ) ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2009-09-12 19:22:56 +02:00
}
2011-09-11 23:35:35 +02:00
if ( o - > nb_audio_sample_rate ) {
snprintf ( buf , sizeof ( buf ) , " %d " , o - > audio_sample_rate [ o - > nb_audio_sample_rate - 1 ] . u . i ) ;
2011-06-09 10:58:23 +02:00
av_dict_set ( & format_opts , " sample_rate " , buf , 0 ) ;
}
2011-09-10 20:52:48 +02:00
if ( o - > nb_audio_channels ) {
snprintf ( buf , sizeof ( buf ) , " %d " , o - > audio_channels [ o - > nb_audio_channels - 1 ] . u . i ) ;
2011-06-09 10:58:23 +02:00
av_dict_set ( & format_opts , " channels " , buf , 0 ) ;
}
2011-09-11 23:35:35 +02:00
if ( o - > nb_frame_rates ) {
av_dict_set ( & format_opts , " framerate " , o - > frame_rates [ o - > nb_frame_rates - 1 ] . u . str , 0 ) ;
2011-06-09 10:58:23 +02:00
}
2011-09-11 23:35:35 +02:00
if ( o - > nb_frame_sizes ) {
av_dict_set ( & format_opts , " video_size " , o - > frame_sizes [ o - > nb_frame_sizes - 1 ] . u . str , 0 ) ;
2011-06-09 10:58:23 +02:00
}
2011-09-11 23:35:35 +02:00
if ( o - > nb_frame_pix_fmts )
av_dict_set ( & format_opts , " pixel_format " , o - > frame_pix_fmts [ o - > nb_frame_pix_fmts - 1 ] . u . str , 0 ) ;
2007-12-19 11:56:17 +01:00
2011-10-26 02:09:31 +02:00
ic - > video_codec_id = video_codec_name ?
find_codec_or_die ( video_codec_name , AVMEDIA_TYPE_VIDEO , 0 ) - > id : CODEC_ID_NONE ;
ic - > audio_codec_id = audio_codec_name ?
find_codec_or_die ( audio_codec_name , AVMEDIA_TYPE_AUDIO , 0 ) - > id : CODEC_ID_NONE ;
ic - > subtitle_codec_id = subtitle_codec_name ?
find_codec_or_die ( subtitle_codec_name , AVMEDIA_TYPE_SUBTITLE , 0 ) - > id : CODEC_ID_NONE ;
2011-06-09 10:58:23 +02:00
ic - > flags | = AVFMT_FLAG_NONBLOCK ;
2011-11-19 01:55:55 +01:00
ic - > interrupt_callback = int_cb ;
2007-12-19 11:56:17 +01:00
2011-08-03 11:45:02 +02:00
if ( loop_input ) {
2011-12-10 21:00:38 +01:00
av_log ( NULL , AV_LOG_WARNING ,
" -loop_input is deprecated, use -loop 1 \n "
" Note, both loop options only work with -f image2 \n "
) ;
2011-08-03 11:45:02 +02:00
ic - > loop_input = loop_input ;
}
2011-12-08 19:34:53 +01:00
/* open the input file with generic avformat function */
2011-06-09 10:58:23 +02:00
err = avformat_open_input ( & ic , filename , file_iformat , & format_opts ) ;
2001-07-22 16:37:44 +02:00
if ( err < 0 ) {
2002-05-20 18:32:49 +02:00
print_error ( filename , err ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2001-07-22 16:37:44 +02:00
}
2011-06-09 10:58:23 +02:00
assert_avoptions ( format_opts ) ;
2011-08-30 04:10:54 +02:00
/* apply forced codec ids */
for ( i = 0 ; i < ic - > nb_streams ; i + + )
2011-10-26 02:09:31 +02:00
choose_decoder ( o , ic , ic - > streams [ i ] ) ;
2011-08-30 04:10:54 +02:00
2011-05-25 17:29:25 +02:00
/* Set AVCodecContext options for avformat_find_stream_info */
2011-07-17 16:19:28 +02:00
opts = setup_find_stream_info_opts ( ic , codec_opts ) ;
2011-05-25 17:29:25 +02:00
orig_nb_streams = ic - > nb_streams ;
2011-04-24 22:48:42 +02:00
2002-05-20 18:32:49 +02:00
/* If not enough info to get the stream parameters, we decode the
first frames to get it . ( used in mpeg case for example ) */
2011-05-25 17:29:25 +02:00
ret = avformat_find_stream_info ( ic , opts ) ;
2011-09-27 02:14:37 +02:00
if ( ret < 0 ) {
av_log ( NULL , AV_LOG_FATAL , " %s: could not find codec parameters \n " , filename ) ;
2011-12-13 00:29:25 +01:00
avformat_close_input ( & ic ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2001-07-22 16:37:44 +02:00
}
2011-09-05 02:04:27 +02:00
timestamp = o - > start_time ;
2004-09-20 17:49:24 +02:00
/* add the stream start time */
if ( ic - > start_time ! = AV_NOPTS_VALUE )
timestamp + = ic - > start_time ;
2003-11-10 19:54:17 +01:00
/* if seeking requested, we execute it */
2011-09-05 02:04:27 +02:00
if ( o - > start_time ! = 0 ) {
2004-10-11 00:05:43 +02:00
ret = av_seek_frame ( ic , - 1 , timestamp , AVSEEK_FLAG_BACKWARD ) ;
2003-11-10 19:54:17 +01:00
if ( ret < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_WARNING , " %s: could not seek to position %0.3f \n " ,
filename , ( double ) timestamp / AV_TIME_BASE ) ;
2003-11-10 19:54:17 +01:00
}
}
2001-07-22 16:37:44 +02:00
/* update the current parameters so that they match the one of the input stream */
2011-09-05 22:10:26 +02:00
add_input_streams ( o , ic ) ;
2005-12-17 19:14:38 +01:00
2001-07-22 16:37:44 +02:00
/* dump the file content */
2011-09-27 02:14:37 +02:00
av_dump_format ( ic , nb_input_files , filename , 0 ) ;
2004-04-11 15:50:42 +02:00
2011-05-22 22:12:35 +02:00
input_files = grow_array ( input_files , sizeof ( * input_files ) , & nb_input_files , nb_input_files + 1 ) ;
input_files [ nb_input_files - 1 ] . ctx = ic ;
input_files [ nb_input_files - 1 ] . ist_index = nb_input_streams - ic - > nb_streams ;
2011-09-05 02:04:27 +02:00
input_files [ nb_input_files - 1 ] . ts_offset = o - > input_ts_offset - ( copy_ts ? 0 : timestamp ) ;
2011-08-04 11:06:43 +02:00
input_files [ nb_input_files - 1 ] . nb_streams = ic - > nb_streams ;
2011-09-09 19:54:04 +02:00
input_files [ nb_input_files - 1 ] . rate_emu = o - > rate_emu ;
2003-03-07 13:37:49 +01:00
2011-11-04 01:44:06 +01:00
for ( i = 0 ; i < o - > nb_dump_attachment ; i + + ) {
int j ;
for ( j = 0 ; j < ic - > nb_streams ; j + + ) {
AVStream * st = ic - > streams [ j ] ;
if ( check_stream_specifier ( ic , st , o - > dump_attachment [ i ] . specifier ) = = 1 )
dump_attachment ( st , o - > dump_attachment [ i ] . u . str ) ;
}
}
2005-12-17 19:14:38 +01:00
2011-05-25 17:29:25 +02:00
for ( i = 0 ; i < orig_nb_streams ; i + + )
av_dict_free ( & opts [ i ] ) ;
av_freep ( & opts ) ;
2011-09-05 02:04:27 +02:00
2011-09-05 03:11:18 +02:00
reset_options ( o , 1 ) ;
2011-05-24 18:14:42 +02:00
return 0 ;
2001-07-22 16:37:44 +02:00
}
2011-10-05 14:01:46 +02:00
static void parse_forced_key_frames ( char * kf , OutputStream * ost )
2011-08-30 04:14:12 +02:00
{
char * p ;
int n = 1 , i ;
for ( p = kf ; * p ; p + + )
if ( * p = = ' , ' )
n + + ;
ost - > forced_kf_count = n ;
2011-12-30 03:46:24 +01:00
ost - > forced_kf_pts = av_malloc ( sizeof ( * ost - > forced_kf_pts ) * n ) ;
2011-08-30 04:14:12 +02:00
if ( ! ost - > forced_kf_pts ) {
av_log ( NULL , AV_LOG_FATAL , " Could not allocate forced key frames array. \n " ) ;
exit_program ( 1 ) ;
}
for ( i = 0 ; i < n ; i + + ) {
p = i ? strchr ( p , ' , ' ) + 1 : kf ;
2011-10-05 14:01:46 +02:00
ost - > forced_kf_pts [ i ] = parse_time_or_die ( " force_key_frames " , p , 1 ) ;
2011-08-30 04:14:12 +02:00
}
}
2011-10-18 01:33:09 +02:00
static uint8_t * get_line ( AVIOContext * s )
{
AVIOContext * line ;
uint8_t * buf ;
char c ;
if ( avio_open_dyn_buf ( & line ) < 0 ) {
av_log ( NULL , AV_LOG_FATAL , " Could not alloc buffer for reading preset. \n " ) ;
exit_program ( 1 ) ;
}
while ( ( c = avio_r8 ( s ) ) & & c ! = ' \n ' )
avio_w8 ( line , c ) ;
avio_w8 ( line , 0 ) ;
avio_close_dyn_buf ( line , & buf ) ;
return buf ;
}
static int get_preset_file_2 ( const char * preset_name , const char * codec_name , AVIOContext * * s )
{
int i , ret = 1 ;
char filename [ 1000 ] ;
const char * base [ 3 ] = { getenv ( " AVCONV_DATADIR " ) ,
getenv ( " HOME " ) ,
AVCONV_DATADIR ,
} ;
for ( i = 0 ; i < FF_ARRAY_ELEMS ( base ) & & ret ; i + + ) {
if ( ! base [ i ] )
continue ;
if ( codec_name ) {
snprintf ( filename , sizeof ( filename ) , " %s%s/%s-%s.avpreset " , base [ i ] ,
i ! = 1 ? " " : " /.avconv " , codec_name , preset_name ) ;
2011-11-19 01:55:55 +01:00
ret = avio_open2 ( s , filename , AVIO_FLAG_READ , & int_cb , NULL ) ;
2011-10-18 01:33:09 +02:00
}
if ( ret ) {
snprintf ( filename , sizeof ( filename ) , " %s%s/%s.avpreset " , base [ i ] ,
i ! = 1 ? " " : " /.avconv " , preset_name ) ;
2011-11-19 01:55:55 +01:00
ret = avio_open2 ( s , filename , AVIO_FLAG_READ , & int_cb , NULL ) ;
2001-09-16 23:47:13 +02:00
}
}
2011-10-18 01:33:09 +02:00
return ret ;
2001-09-16 23:47:13 +02:00
}
2011-10-26 02:09:31 +02:00
static void choose_encoder ( OptionsContext * o , AVFormatContext * s , OutputStream * ost )
{
char * codec_name = NULL ;
MATCH_PER_STREAM_OPT ( codec_names , str , codec_name , s , ost - > st ) ;
if ( ! codec_name ) {
ost - > st - > codec - > codec_id = av_guess_codec ( s - > oformat , NULL , s - > filename ,
NULL , ost - > st - > codec - > codec_type ) ;
ost - > enc = avcodec_find_encoder ( ost - > st - > codec - > codec_id ) ;
} else if ( ! strcmp ( codec_name , " copy " ) )
ost - > stream_copy = 1 ;
else {
ost - > enc = find_codec_or_die ( codec_name , ost - > st - > codec - > codec_type , 1 ) ;
ost - > st - > codec - > codec_id = ost - > enc - > id ;
}
}
2011-09-05 22:10:26 +02:00
static OutputStream * new_output_stream ( OptionsContext * o , AVFormatContext * oc , enum AVMediaType type )
2011-08-30 04:19:26 +02:00
{
OutputStream * ost ;
2011-10-20 02:23:36 +02:00
AVStream * st = avformat_new_stream ( oc , NULL ) ;
2011-10-18 01:33:09 +02:00
int idx = oc - > nb_streams - 1 , ret = 0 ;
2011-09-10 20:52:48 +02:00
char * bsf = NULL , * next , * codec_tag = NULL ;
2011-09-05 22:10:26 +02:00
AVBitStreamFilterContext * bsfc , * bsfc_prev = NULL ;
2011-09-11 23:35:35 +02:00
double qscale = - 1 ;
2011-10-18 01:33:09 +02:00
char * buf = NULL , * arg = NULL , * preset = NULL ;
AVIOContext * s = NULL ;
2011-08-30 04:19:26 +02:00
if ( ! st ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Could not alloc stream. \n " ) ;
2011-08-30 04:19:26 +02:00
exit_program ( 1 ) ;
}
2011-10-20 02:23:36 +02:00
if ( oc - > nb_streams - 1 < o - > nb_streamid_map )
st - > id = o - > streamid_map [ oc - > nb_streams - 1 ] ;
2011-08-30 15:03:53 +02:00
output_streams = grow_array ( output_streams , sizeof ( * output_streams ) , & nb_output_streams ,
nb_output_streams + 1 ) ;
ost = & output_streams [ nb_output_streams - 1 ] ;
2011-08-30 04:20:25 +02:00
ost - > file_index = nb_output_files ;
2011-12-30 03:46:24 +01:00
ost - > index = idx ;
ost - > st = st ;
2011-08-30 04:19:26 +02:00
st - > codec - > codec_type = type ;
2011-10-26 02:09:31 +02:00
choose_encoder ( o , oc , ost ) ;
2011-08-30 04:19:26 +02:00
if ( ost - > enc ) {
2011-11-27 21:17:56 +01:00
ost - > opts = filter_codec_opts ( codec_opts , ost - > enc , oc , st ) ;
2011-08-30 04:19:26 +02:00
}
avcodec_get_context_defaults3 ( st - > codec , ost - > enc ) ;
st - > codec - > codec_type = type ; // XXX hack, avcodec_get_context_defaults2() sets type to unknown for stream copy
2011-10-18 01:33:09 +02:00
MATCH_PER_STREAM_OPT ( presets , str , preset , oc , st ) ;
if ( preset & & ( ! ( ret = get_preset_file_2 ( preset , ost - > enc - > name , & s ) ) ) ) {
do {
buf = get_line ( s ) ;
if ( ! buf [ 0 ] | | buf [ 0 ] = = ' # ' ) {
av_free ( buf ) ;
continue ;
}
if ( ! ( arg = strchr ( buf , ' = ' ) ) ) {
av_log ( NULL , AV_LOG_FATAL , " Invalid line found in the preset file. \n " ) ;
exit_program ( 1 ) ;
}
* arg + + = 0 ;
av_dict_set ( & ost - > opts , buf , arg , AV_DICT_DONT_OVERWRITE ) ;
av_free ( buf ) ;
} while ( ! s - > eof_reached ) ;
avio_close ( s ) ;
}
if ( ret ) {
av_log ( NULL , AV_LOG_FATAL ,
" Preset %s specified for stream %d:%d, but could not be opened. \n " ,
preset , ost - > file_index , ost - > index ) ;
exit_program ( 1 ) ;
}
2011-11-07 02:41:01 +01:00
ost - > max_frames = INT64_MAX ;
MATCH_PER_STREAM_OPT ( max_frames , i64 , ost - > max_frames , oc , st ) ;
2011-09-05 22:10:26 +02:00
MATCH_PER_STREAM_OPT ( bitstream_filters , str , bsf , oc , st ) ;
while ( bsf ) {
if ( next = strchr ( bsf , ' , ' ) )
* next + + = 0 ;
if ( ! ( bsfc = av_bitstream_filter_init ( bsf ) ) ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Unknown bitstream filter %s \n " , bsf ) ;
2011-09-05 22:10:26 +02:00
exit_program ( 1 ) ;
2001-09-16 23:47:13 +02:00
}
2011-09-05 22:10:26 +02:00
if ( bsfc_prev )
bsfc_prev - > next = bsfc ;
else
ost - > bitstream_filters = bsfc ;
bsfc_prev = bsfc ;
bsf = next ;
2001-09-16 23:47:13 +02:00
}
2011-09-05 22:10:26 +02:00
2011-09-10 20:52:48 +02:00
MATCH_PER_STREAM_OPT ( codec_tags , str , codec_tag , oc , st ) ;
if ( codec_tag ) {
uint32_t tag = strtol ( codec_tag , & next , 0 ) ;
if ( * next )
tag = AV_RL32 ( codec_tag ) ;
st - > codec - > codec_tag = tag ;
2001-09-16 23:47:13 +02:00
}
2011-09-10 20:52:48 +02:00
2011-09-11 23:35:35 +02:00
MATCH_PER_STREAM_OPT ( qscale , dbl , qscale , oc , st ) ;
if ( qscale > = 0 | | same_quant ) {
st - > codec - > flags | = CODEC_FLAG_QSCALE ;
st - > codec - > global_quality = FF_QP2LAMBDA * qscale ;
}
2006-07-06 17:04:46 +02:00
2011-09-28 01:31:38 +02:00
if ( oc - > oformat - > flags & AVFMT_GLOBALHEADER )
st - > codec - > flags | = CODEC_FLAG_GLOBAL_HEADER ;
2006-07-06 17:04:46 +02:00
2011-10-13 04:55:40 +02:00
av_opt_get_int ( sws_opts , " sws_flags " , 0 , & ost - > sws_flags ) ;
2011-08-30 04:19:26 +02:00
return ost ;
}
2011-09-11 23:35:35 +02:00
static void parse_matrix_coeffs ( uint16_t * dest , const char * str )
{
int i ;
const char * p = str ;
2011-12-30 03:46:24 +01:00
for ( i = 0 ; ; i + + ) {
2011-09-11 23:35:35 +02:00
dest [ i ] = atoi ( p ) ;
2011-12-30 03:46:24 +01:00
if ( i = = 63 )
2011-09-11 23:35:35 +02:00
break ;
p = strchr ( p , ' , ' ) ;
2011-12-30 03:46:24 +01:00
if ( ! p ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Syntax error in matrix \" %s \" at coeff %d \n " , str , i ) ;
2011-09-11 23:35:35 +02:00
exit_program ( 1 ) ;
}
p + + ;
}
}
2005-12-17 19:14:38 +01:00
2011-09-05 22:10:26 +02:00
static OutputStream * new_video_stream ( OptionsContext * o , AVFormatContext * oc )
2001-07-22 16:37:44 +02:00
{
AVStream * st ;
2011-06-23 19:14:08 +02:00
OutputStream * ost ;
2005-06-03 16:31:45 +02:00
AVCodecContext * video_enc ;
2011-02-14 23:02:10 +01:00
2011-09-05 22:10:26 +02:00
ost = new_output_stream ( o , oc , AVMEDIA_TYPE_VIDEO ) ;
2011-06-25 07:43:49 +02:00
st = ost - > st ;
2005-07-18 00:24:36 +02:00
video_enc = st - > codec ;
2005-12-17 19:14:38 +01:00
2011-10-26 02:09:31 +02:00
if ( ! ost - > stream_copy ) {
2011-09-11 23:35:35 +02:00
const char * p = NULL ;
char * forced_key_frames = NULL , * frame_rate = NULL , * frame_size = NULL ;
char * frame_aspect_ratio = NULL , * frame_pix_fmt = NULL ;
char * intra_matrix = NULL , * inter_matrix = NULL , * filters = NULL ;
2005-06-03 16:31:45 +02:00
int i ;
2011-09-11 23:35:35 +02:00
MATCH_PER_STREAM_OPT ( frame_rates , str , frame_rate , oc , st ) ;
if ( frame_rate & & av_parse_video_rate ( & ost - > frame_rate , frame_rate ) < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Invalid framerate value: %s \n " , frame_rate ) ;
2011-09-11 23:35:35 +02:00
exit_program ( 1 ) ;
}
2005-12-17 19:14:38 +01:00
2011-09-11 23:35:35 +02:00
MATCH_PER_STREAM_OPT ( frame_sizes , str , frame_size , oc , st ) ;
if ( frame_size & & av_parse_video_size ( & video_enc - > width , & video_enc - > height , frame_size ) < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Invalid frame size: %s. \n " , frame_size ) ;
2011-09-11 23:35:35 +02:00
exit_program ( 1 ) ;
}
2005-12-17 19:14:38 +01:00
2011-09-11 23:35:35 +02:00
MATCH_PER_STREAM_OPT ( frame_aspect_ratios , str , frame_aspect_ratio , oc , st ) ;
if ( frame_aspect_ratio )
ost - > frame_aspect_ratio = parse_frame_aspect_ratio ( frame_aspect_ratio ) ;
2005-12-17 19:14:38 +01:00
2011-04-03 02:14:00 +02:00
video_enc - > bits_per_raw_sample = frame_bits_per_raw_sample ;
2011-09-11 23:35:35 +02:00
MATCH_PER_STREAM_OPT ( frame_pix_fmts , str , frame_pix_fmt , oc , st ) ;
if ( frame_pix_fmt & & ( video_enc - > pix_fmt = av_get_pix_fmt ( frame_pix_fmt ) ) = = PIX_FMT_NONE ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Unknown pixel format requested: %s. \n " , frame_pix_fmt ) ;
2011-09-11 23:35:35 +02:00
exit_program ( 1 ) ;
}
2008-08-24 01:13:58 +02:00
st - > sample_aspect_ratio = video_enc - > sample_aspect_ratio ;
2005-06-03 16:31:45 +02:00
2006-09-15 19:40:46 +02:00
if ( intra_only )
2005-06-03 16:31:45 +02:00
video_enc - > gop_size = 0 ;
2011-09-11 23:35:35 +02:00
MATCH_PER_STREAM_OPT ( intra_matrices , str , intra_matrix , oc , st ) ;
if ( intra_matrix ) {
if ( ! ( video_enc - > intra_matrix = av_mallocz ( sizeof ( * video_enc - > intra_matrix ) * 64 ) ) ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Could not allocate memory for intra matrix. \n " ) ;
2011-09-11 23:35:35 +02:00
exit_program ( 1 ) ;
}
parse_matrix_coeffs ( video_enc - > intra_matrix , intra_matrix ) ;
}
MATCH_PER_STREAM_OPT ( inter_matrices , str , inter_matrix , oc , st ) ;
if ( inter_matrix ) {
if ( ! ( video_enc - > inter_matrix = av_mallocz ( sizeof ( * video_enc - > inter_matrix ) * 64 ) ) ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Could not allocate memory for inter matrix. \n " ) ;
2011-09-11 23:35:35 +02:00
exit_program ( 1 ) ;
}
parse_matrix_coeffs ( video_enc - > inter_matrix , inter_matrix ) ;
2005-06-03 16:31:45 +02:00
}
2011-09-11 23:35:35 +02:00
MATCH_PER_STREAM_OPT ( rc_overrides , str , p , oc , st ) ;
2011-12-30 03:46:24 +01:00
for ( i = 0 ; p ; i + + ) {
2005-06-03 16:31:45 +02:00
int start , end , q ;
2011-12-30 03:46:24 +01:00
int e = sscanf ( p , " %d,%d,%d " , & start , & end , & q ) ;
if ( e ! = 3 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " error parsing rc_override \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2005-06-03 16:31:45 +02:00
}
2011-09-28 17:16:11 +02:00
/* FIXME realloc failure */
2011-12-30 03:46:24 +01:00
video_enc - > rc_override =
2005-12-17 19:14:38 +01:00
av_realloc ( video_enc - > rc_override ,
2011-12-30 03:46:24 +01:00
sizeof ( RcOverride ) * ( i + 1 ) ) ;
video_enc - > rc_override [ i ] . start_frame = start ;
video_enc - > rc_override [ i ] . end_frame = end ;
if ( q > 0 ) {
video_enc - > rc_override [ i ] . qscale = q ;
video_enc - > rc_override [ i ] . quality_factor = 1.0 ;
2005-06-03 16:31:45 +02:00
}
2011-12-30 03:46:24 +01:00
else {
video_enc - > rc_override [ i ] . qscale = 0 ;
video_enc - > rc_override [ i ] . quality_factor = - q / 100.0 ;
2005-06-03 16:31:45 +02:00
}
2011-12-30 03:46:24 +01:00
p = strchr ( p , ' / ' ) ;
if ( p ) p + + ;
2005-06-03 16:31:45 +02:00
}
2011-12-30 03:46:24 +01:00
video_enc - > rc_override_count = i ;
2007-01-22 11:01:14 +01:00
if ( ! video_enc - > rc_initial_buffer_occupancy )
2011-12-30 03:46:24 +01:00
video_enc - > rc_initial_buffer_occupancy = video_enc - > rc_buffer_size * 3 / 4 ;
video_enc - > intra_dc_precision = intra_dc_precision - 8 ;
2005-06-03 16:31:45 +02:00
2011-11-09 18:58:07 +01:00
if ( do_psnr )
video_enc - > flags | = CODEC_FLAG_PSNR ;
2005-06-03 16:31:45 +02:00
/* two pass mode */
if ( do_pass ) {
2011-10-30 02:26:48 +01:00
if ( do_pass & 1 ) {
2005-06-03 16:31:45 +02:00
video_enc - > flags | = CODEC_FLAG_PASS1 ;
2011-10-30 02:26:48 +01:00
}
if ( do_pass & 2 ) {
2005-06-03 16:31:45 +02:00
video_enc - > flags | = CODEC_FLAG_PASS2 ;
}
}
2010-10-18 23:47:15 +02:00
2011-09-11 23:35:35 +02:00
MATCH_PER_STREAM_OPT ( forced_key_frames , str , forced_key_frames , oc , st ) ;
2010-10-18 23:47:15 +02:00
if ( forced_key_frames )
2011-10-05 14:01:46 +02:00
parse_forced_key_frames ( forced_key_frames , ost ) ;
2011-09-11 23:35:35 +02:00
2011-11-07 02:41:01 +01:00
MATCH_PER_STREAM_OPT ( force_fps , i , ost - > force_fps , oc , st ) ;
ost - > top_field_first = - 1 ;
MATCH_PER_STREAM_OPT ( top_field_first , i , ost - > top_field_first , oc , st ) ;
2011-09-11 23:35:35 +02:00
2011-11-07 02:41:01 +01:00
MATCH_PER_STREAM_OPT ( copy_initial_nonkeyframes , i , ost - > copy_initial_nonkeyframes , oc , st ) ;
2011-09-11 23:35:35 +02:00
# if CONFIG_AVFILTER
MATCH_PER_STREAM_OPT ( filters , str , filters , oc , st ) ;
if ( filters )
ost - > avfilter = av_strdup ( filters ) ;
# endif
2005-06-03 16:31:45 +02:00
}
2011-08-30 04:05:20 +02:00
return ost ;
2005-06-03 16:31:45 +02:00
}
2011-09-05 22:10:26 +02:00
static OutputStream * new_audio_stream ( OptionsContext * o , AVFormatContext * oc )
2005-06-03 16:31:45 +02:00
{
2011-11-04 18:54:01 +01:00
int n ;
2005-06-03 16:31:45 +02:00
AVStream * st ;
2011-06-23 19:14:08 +02:00
OutputStream * ost ;
2005-06-03 16:31:45 +02:00
AVCodecContext * audio_enc ;
2005-12-17 19:14:38 +01:00
2011-09-05 22:10:26 +02:00
ost = new_output_stream ( o , oc , AVMEDIA_TYPE_AUDIO ) ;
2011-06-25 07:43:49 +02:00
st = ost - > st ;
2006-07-06 17:04:46 +02:00
2005-07-18 00:24:36 +02:00
audio_enc = st - > codec ;
2010-03-31 01:30:55 +02:00
audio_enc - > codec_type = AVMEDIA_TYPE_AUDIO ;
2005-12-17 19:14:38 +01:00
2011-10-26 02:09:31 +02:00
if ( ! ost - > stream_copy ) {
2011-09-11 23:35:35 +02:00
char * sample_fmt = NULL ;
2005-12-17 19:14:38 +01:00
2011-09-10 20:52:48 +02:00
MATCH_PER_STREAM_OPT ( audio_channels , i , audio_enc - > channels , oc , st ) ;
2011-09-11 23:35:35 +02:00
MATCH_PER_STREAM_OPT ( sample_fmts , str , sample_fmt , oc , st ) ;
if ( sample_fmt & &
( audio_enc - > sample_fmt = av_get_sample_fmt ( sample_fmt ) ) = = AV_SAMPLE_FMT_NONE ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Invalid sample format '%s' \n " , sample_fmt ) ;
2011-09-11 23:35:35 +02:00
exit_program ( 1 ) ;
2005-08-21 22:27:00 +02:00
}
2011-09-11 23:35:35 +02:00
MATCH_PER_STREAM_OPT ( audio_sample_rate , i , audio_enc - > sample_rate , oc , st ) ;
2011-10-26 00:45:52 +02:00
ost - > rematrix_volume = 1.0 ;
MATCH_PER_STREAM_OPT ( rematrix_volume , f , ost - > rematrix_volume , oc , st ) ;
2005-06-03 16:31:45 +02:00
}
2011-08-30 04:05:20 +02:00
2011-11-04 18:54:01 +01:00
/* check for channel mapping for this audio stream */
for ( n = 0 ; n < o - > nb_audio_channel_maps ; n + + ) {
AudioChannelMap * map = & o - > audio_channel_maps [ n ] ;
InputStream * ist = & input_streams [ ost - > source_index ] ;
if ( ( map - > channel_idx = = - 1 | | ( ist - > file_index = = map - > file_idx & & ist - > st - > index = = map - > stream_idx ) ) & &
( map - > ofile_idx = = - 1 | | ost - > file_index = = map - > ofile_idx ) & &
( map - > ostream_idx = = - 1 | | ost - > st - > index = = map - > ostream_idx ) ) {
if ( ost - > audio_channels_mapped < FF_ARRAY_ELEMS ( ost - > audio_channels_map ) )
ost - > audio_channels_map [ ost - > audio_channels_mapped + + ] = map - > channel_idx ;
else
av_log ( NULL , AV_LOG_FATAL , " Max channel mapping for output %d.%d reached \n " ,
ost - > file_index , ost - > st - > index ) ;
}
}
2011-08-30 04:05:20 +02:00
return ost ;
2005-06-03 16:31:45 +02:00
}
2011-09-05 22:10:26 +02:00
static OutputStream * new_data_stream ( OptionsContext * o , AVFormatContext * oc )
2011-04-14 13:32:36 +02:00
{
2011-06-25 07:43:49 +02:00
OutputStream * ost ;
2011-04-14 13:32:36 +02:00
2011-09-05 22:10:26 +02:00
ost = new_output_stream ( o , oc , AVMEDIA_TYPE_DATA ) ;
2011-10-26 02:09:31 +02:00
if ( ! ost - > stream_copy ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Data stream encoding not supported yet (only streamcopy) \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2011-04-14 13:32:36 +02:00
}
2011-09-28 01:31:38 +02:00
return ost ;
}
2011-04-14 13:32:36 +02:00
2011-09-28 01:31:38 +02:00
static OutputStream * new_attachment_stream ( OptionsContext * o , AVFormatContext * oc )
{
OutputStream * ost = new_output_stream ( o , oc , AVMEDIA_TYPE_ATTACHMENT ) ;
2011-10-26 02:09:31 +02:00
ost - > stream_copy = 1 ;
2011-08-30 04:05:20 +02:00
return ost ;
2011-04-14 13:32:36 +02:00
}
2011-09-05 22:10:26 +02:00
static OutputStream * new_subtitle_stream ( OptionsContext * o , AVFormatContext * oc )
2005-06-03 16:31:45 +02:00
{
AVStream * st ;
2011-06-23 19:14:08 +02:00
OutputStream * ost ;
2005-06-03 16:31:45 +02:00
AVCodecContext * subtitle_enc ;
2005-12-17 19:14:38 +01:00
2011-09-05 22:10:26 +02:00
ost = new_output_stream ( o , oc , AVMEDIA_TYPE_SUBTITLE ) ;
2011-06-25 07:43:49 +02:00
st = ost - > st ;
subtitle_enc = st - > codec ;
2005-06-03 16:31:45 +02:00
2010-03-31 01:30:55 +02:00
subtitle_enc - > codec_type = AVMEDIA_TYPE_SUBTITLE ;
2009-03-11 09:14:19 +01:00
2011-08-30 04:05:20 +02:00
return ost ;
2007-07-25 21:47:44 +02:00
}
2010-07-01 00:35:57 +02:00
/* arg format is "output-stream-index:streamid-value". */
2011-09-11 23:35:35 +02:00
static int opt_streamid ( OptionsContext * o , const char * opt , const char * arg )
2010-07-01 00:35:57 +02:00
{
int idx ;
char * p ;
char idx_str [ 16 ] ;
2011-05-03 20:19:31 +02:00
av_strlcpy ( idx_str , arg , sizeof ( idx_str ) ) ;
2010-07-01 00:35:57 +02:00
p = strchr ( idx_str , ' : ' ) ;
if ( ! p ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL ,
" Invalid value '%s' for option '%s', required syntax is 'index:value' \n " ,
arg , opt ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2010-07-01 00:35:57 +02:00
}
* p + + = ' \0 ' ;
2011-07-16 19:24:10 +02:00
idx = parse_number_or_die ( opt , idx_str , OPT_INT , 0 , MAX_STREAMS - 1 ) ;
2011-09-11 23:35:35 +02:00
o - > streamid_map = grow_array ( o - > streamid_map , sizeof ( * o - > streamid_map ) , & o - > nb_streamid_map , idx + 1 ) ;
o - > streamid_map [ idx ] = parse_number_or_die ( opt , p , OPT_INT , 0 , INT_MAX ) ;
2010-10-05 23:05:07 +02:00
return 0 ;
2010-07-01 00:35:57 +02:00
}
2011-08-30 04:19:26 +02:00
2011-09-05 22:10:26 +02:00
static int copy_chapters ( InputFile * ifile , OutputFile * ofile , int copy_metadata )
2011-08-30 04:15:30 +02:00
{
2011-09-05 02:04:27 +02:00
AVFormatContext * is = ifile - > ctx ;
AVFormatContext * os = ofile - > ctx ;
2011-08-30 04:15:30 +02:00
int i ;
for ( i = 0 ; i < is - > nb_chapters ; i + + ) {
AVChapter * in_ch = is - > chapters [ i ] , * out_ch ;
2011-09-05 02:04:27 +02:00
int64_t ts_off = av_rescale_q ( ofile - > start_time - ifile - > ts_offset ,
2011-12-30 03:46:24 +01:00
AV_TIME_BASE_Q , in_ch - > time_base ) ;
2011-09-05 02:04:27 +02:00
int64_t rt = ( ofile - > recording_time = = INT64_MAX ) ? INT64_MAX :
av_rescale_q ( ofile - > recording_time , AV_TIME_BASE_Q , in_ch - > time_base ) ;
2011-08-30 04:15:30 +02:00
if ( in_ch - > end < ts_off )
continue ;
if ( rt ! = INT64_MAX & & in_ch - > start > rt + ts_off )
break ;
out_ch = av_mallocz ( sizeof ( AVChapter ) ) ;
if ( ! out_ch )
return AVERROR ( ENOMEM ) ;
out_ch - > id = in_ch - > id ;
out_ch - > time_base = in_ch - > time_base ;
out_ch - > start = FFMAX ( 0 , in_ch - > start - ts_off ) ;
out_ch - > end = FFMIN ( rt , in_ch - > end - ts_off ) ;
2011-09-05 22:10:26 +02:00
if ( copy_metadata )
2011-08-30 04:15:30 +02:00
av_dict_copy ( & out_ch - > metadata , in_ch - > metadata , 0 ) ;
os - > nb_chapters + + ;
2011-09-28 17:16:11 +02:00
os - > chapters = av_realloc_f ( os - > chapters , os - > nb_chapters , sizeof ( AVChapter ) ) ;
2011-08-30 04:15:30 +02:00
if ( ! os - > chapters )
return AVERROR ( ENOMEM ) ;
os - > chapters [ os - > nb_chapters - 1 ] = out_ch ;
}
return 0 ;
}
2011-09-05 22:10:26 +02:00
static int read_ffserver_streams ( OptionsContext * o , AVFormatContext * s , const char * filename )
{
int i , err ;
2011-11-19 01:55:55 +01:00
AVFormatContext * ic = avformat_alloc_context ( ) ;
2011-09-05 22:10:26 +02:00
2011-11-19 01:55:55 +01:00
ic - > interrupt_callback = int_cb ;
2011-09-05 22:10:26 +02:00
err = avformat_open_input ( & ic , filename , NULL , NULL ) ;
if ( err < 0 )
return err ;
/* copy stream format */
for ( i = 0 ; i < ic - > nb_streams ; i + + ) {
AVStream * st ;
OutputStream * ost ;
AVCodec * codec ;
2011-10-29 20:21:59 +02:00
AVCodecContext * avctx ;
2011-09-05 22:10:26 +02:00
codec = avcodec_find_encoder ( ic - > streams [ i ] - > codec - > codec_id ) ;
ost = new_output_stream ( o , s , codec - > type ) ;
st = ost - > st ;
2011-10-29 20:21:59 +02:00
avctx = st - > codec ;
2011-12-12 17:30:55 +01:00
ost - > enc = codec ;
2011-09-05 22:10:26 +02:00
// FIXME: a more elegant solution is needed
memcpy ( st , ic - > streams [ i ] , sizeof ( AVStream ) ) ;
st - > info = av_malloc ( sizeof ( * st - > info ) ) ;
memcpy ( st - > info , ic - > streams [ i ] - > info , sizeof ( * st - > info ) ) ;
2011-10-29 20:21:59 +02:00
st - > codec = avctx ;
2011-09-05 22:10:26 +02:00
avcodec_copy_context ( st - > codec , ic - > streams [ i ] - > codec ) ;
2011-10-26 02:09:31 +02:00
if ( st - > codec - > codec_type = = AVMEDIA_TYPE_AUDIO & & ! ost - > stream_copy )
2011-09-05 22:10:26 +02:00
choose_sample_fmt ( st , codec ) ;
2011-10-26 02:09:31 +02:00
else if ( st - > codec - > codec_type = = AVMEDIA_TYPE_VIDEO & & ! ost - > stream_copy )
2011-09-05 22:10:26 +02:00
choose_pixel_fmt ( st , codec ) ;
}
2012-01-03 00:28:05 +01:00
avformat_close_input ( & ic ) ;
2011-09-05 22:10:26 +02:00
return 0 ;
}
2011-08-28 14:43:54 +02:00
static void opt_output_file ( void * optctx , const char * filename )
2005-06-03 16:31:45 +02:00
{
2011-09-05 02:04:27 +02:00
OptionsContext * o = optctx ;
2005-06-03 16:31:45 +02:00
AVFormatContext * oc ;
2011-08-30 04:05:20 +02:00
int i , err ;
2009-10-30 10:57:34 +01:00
AVOutputFormat * file_oformat ;
2011-08-30 04:05:20 +02:00
OutputStream * ost ;
InputStream * ist ;
2001-07-22 16:37:44 +02:00
if ( ! strcmp ( filename , " - " ) )
filename = " pipe: " ;
2011-09-05 02:04:27 +02:00
err = avformat_alloc_output_context2 ( & oc , NULL , o - > format , filename ) ;
2009-09-12 19:22:56 +02:00
if ( ! oc ) {
2011-05-19 22:09:34 +02:00
print_error ( filename , err ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2009-09-12 19:22:56 +02:00
}
2011-04-30 20:43:16 +02:00
file_oformat = oc - > oformat ;
2011-11-19 01:55:55 +01:00
oc - > interrupt_callback = int_cb ;
2001-07-22 16:37:44 +02:00
2005-12-17 19:14:38 +01:00
if ( ! strcmp ( file_oformat - > name , " ffm " ) & &
2007-06-24 13:27:12 +02:00
av_strstart ( filename , " http: " , NULL ) ) {
2011-10-29 20:25:39 +02:00
int j ;
2001-07-22 16:37:44 +02:00
/* special case for files sent to ffserver: we get the stream
parameters from ffserver */
2011-09-05 22:10:26 +02:00
int err = read_ffserver_streams ( o , oc , filename ) ;
2008-06-13 00:30:01 +02:00
if ( err < 0 ) {
print_error ( filename , err ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2001-07-22 16:37:44 +02:00
}
2011-10-29 20:25:39 +02:00
for ( j = nb_output_streams - oc - > nb_streams ; j < nb_output_streams ; j + + ) {
ost = & output_streams [ j ] ;
for ( i = 0 ; i < nb_input_streams ; i + + ) {
ist = & input_streams [ i ] ;
if ( ist - > st - > codec - > codec_type = = ost - > st - > codec - > codec_type ) {
ost - > sync_ist = ist ;
ost - > source_index = i ;
ist - > discard = 0 ;
break ;
}
}
2011-11-21 23:32:39 +01:00
if ( ! ost - > sync_ist ) {
av_log ( NULL , AV_LOG_FATAL , " Missing %s stream which is required by this ffm \n " , av_get_media_type_string ( ost - > st - > codec - > codec_type ) ) ;
exit_program ( 1 ) ;
}
2011-10-29 20:25:39 +02:00
}
2011-09-05 02:04:27 +02:00
} else if ( ! o - > nb_stream_maps ) {
2011-08-30 04:05:20 +02:00
/* pick the "best" stream of each type */
# define NEW_STREAM(type, index)\
if ( index > = 0 ) { \
2011-09-05 22:10:26 +02:00
ost = new_ # # type # # _stream ( o , oc ) ; \
2011-08-30 04:05:20 +02:00
ost - > source_index = index ; \
ost - > sync_ist = & input_streams [ index ] ; \
input_streams [ index ] . discard = 0 ; \
}
/* video: highest resolution */
2011-09-10 20:52:48 +02:00
if ( ! o - > video_disable & & oc - > oformat - > video_codec ! = CODEC_ID_NONE ) {
2011-08-30 04:05:20 +02:00
int area = 0 , idx = - 1 ;
for ( i = 0 ; i < nb_input_streams ; i + + ) {
ist = & input_streams [ i ] ;
if ( ist - > st - > codec - > codec_type = = AVMEDIA_TYPE_VIDEO & &
ist - > st - > codec - > width * ist - > st - > codec - > height > area ) {
area = ist - > st - > codec - > width * ist - > st - > codec - > height ;
idx = i ;
}
}
NEW_STREAM ( video , idx ) ;
}
/* audio: most channels */
2011-09-10 20:52:48 +02:00
if ( ! o - > audio_disable & & oc - > oformat - > audio_codec ! = CODEC_ID_NONE ) {
2011-08-30 04:05:20 +02:00
int channels = 0 , idx = - 1 ;
for ( i = 0 ; i < nb_input_streams ; i + + ) {
ist = & input_streams [ i ] ;
if ( ist - > st - > codec - > codec_type = = AVMEDIA_TYPE_AUDIO & &
ist - > st - > codec - > channels > channels ) {
channels = ist - > st - > codec - > channels ;
idx = i ;
}
}
NEW_STREAM ( audio , idx ) ;
}
/* subtitles: pick first */
2011-09-10 20:52:48 +02:00
if ( ! o - > subtitle_disable & & ( oc - > oformat - > subtitle_codec ! = CODEC_ID_NONE | | subtitle_codec_name ) ) {
2011-08-30 04:05:20 +02:00
for ( i = 0 ; i < nb_input_streams ; i + + )
if ( input_streams [ i ] . st - > codec - > codec_type = = AVMEDIA_TYPE_SUBTITLE ) {
NEW_STREAM ( subtitle , i ) ;
break ;
}
}
/* do something with data? */
2001-07-22 16:37:44 +02:00
} else {
2011-09-05 02:04:27 +02:00
for ( i = 0 ; i < o - > nb_stream_maps ; i + + ) {
StreamMap * map = & o - > stream_maps [ i ] ;
2011-08-30 04:05:20 +02:00
2011-08-30 04:06:24 +02:00
if ( map - > disabled )
continue ;
2011-08-30 04:05:20 +02:00
ist = & input_streams [ input_files [ map - > file_index ] . ist_index + map - > stream_index ] ;
2011-10-06 21:59:50 +02:00
if ( o - > subtitle_disable & & ist - > st - > codec - > codec_type = = AVMEDIA_TYPE_SUBTITLE )
continue ;
if ( o - > audio_disable & & ist - > st - > codec - > codec_type = = AVMEDIA_TYPE_AUDIO )
continue ;
if ( o - > video_disable & & ist - > st - > codec - > codec_type = = AVMEDIA_TYPE_VIDEO )
continue ;
2011-12-01 18:02:04 +01:00
if ( o - > data_disable & & ist - > st - > codec - > codec_type = = AVMEDIA_TYPE_DATA )
continue ;
2011-10-06 21:59:50 +02:00
2011-08-30 04:05:20 +02:00
switch ( ist - > st - > codec - > codec_type ) {
2011-09-05 22:10:26 +02:00
case AVMEDIA_TYPE_VIDEO : ost = new_video_stream ( o , oc ) ; break ;
case AVMEDIA_TYPE_AUDIO : ost = new_audio_stream ( o , oc ) ; break ;
case AVMEDIA_TYPE_SUBTITLE : ost = new_subtitle_stream ( o , oc ) ; break ;
case AVMEDIA_TYPE_DATA : ost = new_data_stream ( o , oc ) ; break ;
2011-09-28 01:31:38 +02:00
case AVMEDIA_TYPE_ATTACHMENT : ost = new_attachment_stream ( o , oc ) ; break ;
2011-08-30 04:05:20 +02:00
default :
2011-11-07 02:41:01 +01:00
av_log ( NULL , AV_LOG_FATAL , " Cannot map stream #%d:%d - unsupported type. \n " ,
2011-08-30 04:05:20 +02:00
map - > file_index , map - > stream_index ) ;
exit_program ( 1 ) ;
}
ost - > source_index = input_files [ map - > file_index ] . ist_index + map - > stream_index ;
2011-12-30 03:46:24 +01:00
ost - > sync_ist = & input_streams [ input_files [ map - > sync_file_index ] . ist_index +
2011-08-30 04:05:20 +02:00
map - > sync_stream_index ] ;
ist - > discard = 0 ;
}
2001-07-22 16:37:44 +02:00
}
2011-11-04 01:44:06 +01:00
/* handle attached files */
for ( i = 0 ; i < o - > nb_attachments ; i + + ) {
AVIOContext * pb ;
uint8_t * attachment ;
const char * p ;
int64_t len ;
2001-07-22 16:37:44 +02:00
2011-11-19 01:55:55 +01:00
if ( ( err = avio_open2 ( & pb , o - > attachments [ i ] , AVIO_FLAG_READ , & int_cb , NULL ) ) < 0 ) {
2011-11-04 01:44:06 +01:00
av_log ( NULL , AV_LOG_FATAL , " Could not open attachment file %s. \n " ,
o - > attachments [ i ] ) ;
2011-08-29 07:03:24 +02:00
exit_program ( 1 ) ;
2001-07-22 16:37:44 +02:00
}
2011-11-04 01:44:06 +01:00
if ( ( len = avio_size ( pb ) ) < = 0 ) {
av_log ( NULL , AV_LOG_FATAL , " Could not get size of the attachment %s. \n " ,
o - > attachments [ i ] ) ;
exit_program ( 1 ) ;
}
if ( ! ( attachment = av_malloc ( len ) ) ) {
av_log ( NULL , AV_LOG_FATAL , " Attachment %s too large to fit into memory. \n " ,
o - > attachments [ i ] ) ;
exit_program ( 1 ) ;
}
avio_read ( pb , attachment , len ) ;
ost = new_attachment_stream ( o , oc ) ;
ost - > stream_copy = 0 ;
ost - > source_index = - 1 ;
ost - > attachment_filename = o - > attachments [ i ] ;
ost - > st - > codec - > extradata = attachment ;
ost - > st - > codec - > extradata_size = len ;
p = strrchr ( o - > attachments [ i ] , ' / ' ) ;
av_dict_set ( & ost - > st - > metadata , " filename " , ( p & & * p ) ? p + 1 : o - > attachments [ i ] , AV_DICT_DONT_OVERWRITE ) ;
avio_close ( pb ) ;
2001-07-22 16:37:44 +02:00
}
2011-08-30 14:19:39 +02:00
output_files = grow_array ( output_files , sizeof ( * output_files ) , & nb_output_files , nb_output_files + 1 ) ;
output_files [ nb_output_files - 1 ] . ctx = oc ;
2011-08-30 15:03:53 +02:00
output_files [ nb_output_files - 1 ] . ost_index = nb_output_streams - oc - > nb_streams ;
2011-09-05 02:04:27 +02:00
output_files [ nb_output_files - 1 ] . recording_time = o - > recording_time ;
output_files [ nb_output_files - 1 ] . start_time = o - > start_time ;
output_files [ nb_output_files - 1 ] . limit_filesize = o - > limit_filesize ;
2011-08-30 14:19:39 +02:00
av_dict_copy ( & output_files [ nb_output_files - 1 ] . opts , format_opts , 0 ) ;
2001-07-22 16:37:44 +02:00
2001-09-16 23:47:13 +02:00
/* check filename in case of an image number is expected */
2002-05-20 18:32:49 +02:00
if ( oc - > oformat - > flags & AVFMT_NEEDNUMBER ) {
2006-09-04 11:57:47 +02:00
if ( ! av_filename_number_test ( oc - > filename ) ) {
2011-04-11 00:29:30 +02:00
print_error ( oc - > filename , AVERROR ( EINVAL ) ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2002-05-20 18:32:49 +02:00
}
2001-09-16 23:47:13 +02:00
}
2002-05-20 18:32:49 +02:00
if ( ! ( oc - > oformat - > flags & AVFMT_NOFILE ) ) {
2011-10-05 14:12:42 +02:00
/* test if it already exists to avoid losing precious files */
2011-11-04 01:44:06 +01:00
assert_file_overwrite ( filename ) ;
2005-12-17 19:14:38 +01:00
2001-07-22 16:37:44 +02:00
/* open the file */
2011-11-19 01:55:55 +01:00
if ( ( err = avio_open2 ( & oc - > pb , filename , AVIO_FLAG_WRITE ,
& oc - > interrupt_callback ,
& output_files [ nb_output_files - 1 ] . opts ) ) < 0 ) {
2010-04-27 00:36:55 +02:00
print_error ( filename , err ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2001-07-22 16:37:44 +02:00
}
}
2011-10-26 02:09:31 +02:00
if ( o - > mux_preload ) {
uint8_t buf [ 64 ] ;
snprintf ( buf , sizeof ( buf ) , " %d " , ( int ) ( o - > mux_preload * AV_TIME_BASE ) ) ;
av_dict_set ( & output_files [ nb_output_files - 1 ] . opts , " preload " , buf , 0 ) ;
}
2011-09-05 22:10:26 +02:00
oc - > max_delay = ( int ) ( o - > mux_max_delay * AV_TIME_BASE ) ;
2004-10-07 00:29:30 +02:00
2011-06-18 09:49:24 +02:00
if ( loop_output > = 0 ) {
av_log ( NULL , AV_LOG_WARNING , " -loop_output is deprecated, use -loop \n " ) ;
oc - > loop_output = loop_output ;
}
2010-07-01 00:35:57 +02:00
2011-12-17 01:36:59 +01:00
/* copy metadata */
for ( i = 0 ; i < o - > nb_metadata_map ; i + + ) {
char * p ;
int in_file_index = strtol ( o - > metadata_map [ i ] . u . str , & p , 0 ) ;
2011-06-15 08:00:03 +02:00
2011-12-17 01:36:59 +01:00
if ( in_file_index < 0 )
continue ;
if ( in_file_index > = nb_input_files ) {
av_log ( NULL , AV_LOG_FATAL , " Invalid input file index %d while processing metadata maps \n " , in_file_index ) ;
exit_program ( 1 ) ;
}
copy_metadata ( o - > metadata_map [ i ] . specifier , * p ? p + 1 : p , oc , input_files [ in_file_index ] . ctx , o ) ;
}
2011-08-30 01:28:08 +02:00
/* copy chapters */
2011-09-05 22:10:26 +02:00
if ( o - > chapters_input_file > = nb_input_files ) {
if ( o - > chapters_input_file = = INT_MAX ) {
2011-08-30 01:28:08 +02:00
/* copy chapters from the first input file that has them*/
2011-09-05 22:10:26 +02:00
o - > chapters_input_file = - 1 ;
2011-08-30 01:28:08 +02:00
for ( i = 0 ; i < nb_input_files ; i + + )
if ( input_files [ i ] . ctx - > nb_chapters ) {
2011-09-05 22:10:26 +02:00
o - > chapters_input_file = i ;
2011-08-30 01:28:08 +02:00
break ;
}
} else {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Invalid input file index %d in chapter mapping. \n " ,
2011-09-05 22:10:26 +02:00
o - > chapters_input_file ) ;
2011-08-30 01:28:08 +02:00
exit_program ( 1 ) ;
}
}
2011-09-05 22:10:26 +02:00
if ( o - > chapters_input_file > = 0 )
copy_chapters ( & input_files [ o - > chapters_input_file ] , & output_files [ nb_output_files - 1 ] ,
2011-09-11 23:35:35 +02:00
! o - > metadata_chapters_manual ) ;
2011-08-30 01:28:08 +02:00
2011-08-30 01:30:11 +02:00
/* copy global metadata by default */
2011-09-11 05:24:26 +02:00
if ( ! o - > metadata_global_manual & & nb_input_files ) {
2011-08-30 01:30:11 +02:00
av_dict_copy ( & oc - > metadata , input_files [ 0 ] . ctx - > metadata ,
AV_DICT_DONT_OVERWRITE ) ;
2011-09-11 05:24:26 +02:00
if ( o - > recording_time ! = INT64_MAX )
av_dict_set ( & oc - > metadata , " duration " , NULL , 0 ) ;
}
2011-09-05 22:10:26 +02:00
if ( ! o - > metadata_streams_manual )
2011-08-30 15:03:53 +02:00
for ( i = output_files [ nb_output_files - 1 ] . ost_index ; i < nb_output_streams ; i + + ) {
2011-11-04 01:44:06 +01:00
InputStream * ist ;
if ( output_streams [ i ] . source_index < 0 ) /* this is true e.g. for attached files */
continue ;
ist = & input_streams [ output_streams [ i ] . source_index ] ;
2011-08-30 15:03:53 +02:00
av_dict_copy ( & output_streams [ i ] . st - > metadata , ist - > st - > metadata , AV_DICT_DONT_OVERWRITE ) ;
2011-08-30 01:30:11 +02:00
}
2011-09-05 22:10:26 +02:00
/* process manually set metadata */
for ( i = 0 ; i < o - > nb_metadata ; i + + ) {
AVDictionary * * m ;
char type , * val ;
2011-12-17 01:36:59 +01:00
const char * stream_spec ;
2012-01-03 00:28:06 +01:00
int index = 0 , j , ret = 0 ;
2011-09-05 22:10:26 +02:00
val = strchr ( o - > metadata [ i ] . u . str , ' = ' ) ;
if ( ! val ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " No '=' character in metadata string %s. \n " ,
2011-09-05 22:10:26 +02:00
o - > metadata [ i ] . u . str ) ;
exit_program ( 1 ) ;
}
* val + + = 0 ;
2011-12-17 01:36:59 +01:00
parse_meta_type ( o - > metadata [ i ] . specifier , & type , & index , & stream_spec ) ;
if ( type = = ' s ' ) {
for ( j = 0 ; j < oc - > nb_streams ; j + + ) {
if ( ( ret = check_stream_specifier ( oc , oc - > streams [ j ] , stream_spec ) ) > 0 ) {
av_dict_set ( & oc - > streams [ j ] - > metadata , o - > metadata [ i ] . u . str , * val ? val : NULL , 0 ) ;
} else if ( ret < 0 )
exit_program ( 1 ) ;
2011-09-05 22:10:26 +02:00
}
2011-12-17 01:36:59 +01:00
printf ( " ret %d, stream_spec %s \n " , ret , stream_spec ) ;
}
else {
switch ( type ) {
case ' g ' :
m = & oc - > metadata ;
break ;
case ' c ' :
if ( index < 0 | | index > = oc - > nb_chapters ) {
av_log ( NULL , AV_LOG_FATAL , " Invalid chapter index %d in metadata specifier. \n " , index ) ;
exit_program ( 1 ) ;
}
m = & oc - > chapters [ index ] - > metadata ;
break ;
default :
av_log ( NULL , AV_LOG_FATAL , " Invalid metadata specifier %s. \n " , o - > metadata [ i ] . specifier ) ;
2011-09-05 22:10:26 +02:00
exit_program ( 1 ) ;
}
2011-12-17 01:36:59 +01:00
av_dict_set ( m , o - > metadata [ i ] . u . str , * val ? val : NULL , 0 ) ;
2011-09-05 22:10:26 +02:00
}
}
2004-10-07 00:29:30 +02:00
2011-09-05 03:11:18 +02:00
reset_options ( o , 0 ) ;
2001-07-22 16:37:44 +02:00
}
2002-10-10 19:09:01 +02:00
/* same option as mencoder */
2011-04-11 13:16:07 +02:00
static int opt_pass ( const char * opt , const char * arg )
2002-10-10 19:09:01 +02:00
{
2011-10-30 02:26:48 +01:00
do_pass = parse_number_or_die ( opt , arg , OPT_INT , 1 , 3 ) ;
2011-04-11 13:16:07 +02:00
return 0 ;
2002-10-10 19:09:01 +02:00
}
2001-09-25 01:22:25 +02:00
2003-02-11 17:35:48 +01:00
static int64_t getutime ( void )
2001-08-13 23:43:02 +02:00
{
2009-01-14 00:44:16 +01:00
# if HAVE_GETRUSAGE
2003-01-11 21:34:38 +01:00
struct rusage rusage ;
getrusage ( RUSAGE_SELF , & rusage ) ;
return ( rusage . ru_utime . tv_sec * 1000000LL ) + rusage . ru_utime . tv_usec ;
2009-01-14 00:44:16 +01:00
# elif HAVE_GETPROCESSTIMES
2007-07-13 18:11:36 +02:00
HANDLE proc ;
FILETIME c , e , k , u ;
proc = GetCurrentProcess ( ) ;
GetProcessTimes ( proc , & c , & e , & k , & u ) ;
return ( ( int64_t ) u . dwHighDateTime < < 32 | u . dwLowDateTime ) / 10 ;
# else
2007-08-07 02:46:36 +02:00
return av_gettime ( ) ;
2007-07-13 18:04:00 +02:00
# endif
2001-08-13 23:43:02 +02:00
}
2001-07-31 01:19:22 +02:00
2010-02-22 23:21:58 +01:00
static int64_t getmaxrss ( void )
{
# if HAVE_GETRUSAGE && HAVE_STRUCT_RUSAGE_RU_MAXRSS
struct rusage rusage ;
getrusage ( RUSAGE_SELF , & rusage ) ;
return ( int64_t ) rusage . ru_maxrss * 1024 ;
# elif HAVE_GETPROCESSMEMORYINFO
HANDLE proc ;
PROCESS_MEMORY_COUNTERS memcounters ;
proc = GetCurrentProcess ( ) ;
memcounters . cb = sizeof ( memcounters ) ;
GetProcessMemoryInfo ( proc , & memcounters , sizeof ( memcounters ) ) ;
return memcounters . PeakPagefileUsage ;
# else
return 0 ;
# endif
}
2011-09-11 23:35:35 +02:00
static int opt_audio_qscale ( OptionsContext * o , const char * opt , const char * arg )
2003-10-31 11:25:21 +01:00
{
2011-09-11 23:35:35 +02:00
return parse_option ( o , " q:a " , arg , options ) ;
2003-10-31 11:25:21 +01:00
}
2009-12-21 03:12:34 +01:00
static void show_usage ( void )
2007-11-15 13:31:58 +01:00
{
2012-01-06 19:08:13 +01:00
av_log ( NULL , AV_LOG_INFO , " Hyper fast Audio and Video encoder \n " ) ;
av_log ( NULL , AV_LOG_INFO , " usage: %s [options] [[infile options] -i infile]... {[outfile options] outfile}... \n " , program_name ) ;
av_log ( NULL , AV_LOG_INFO , " \n " ) ;
2009-12-21 03:12:34 +01:00
}
2011-06-29 18:38:46 +02:00
static int opt_help ( const char * opt , const char * arg )
2009-12-21 03:12:34 +01:00
{
2011-10-13 04:55:40 +02:00
int flags = AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM ;
2009-12-21 03:12:34 +01:00
av_log_set_callback ( log_callback_help ) ;
show_usage ( ) ;
2007-11-15 13:31:58 +01:00
show_help_options ( options , " Main options: \n " ,
2008-06-16 12:00:32 +02:00
OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB , 0 ) ;
2008-06-17 12:11:46 +02:00
show_help_options ( options , " \n Advanced options: \n " ,
OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB ,
OPT_EXPERT ) ;
2007-11-15 13:31:58 +01:00
show_help_options ( options , " \n Video options: \n " ,
OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB ,
OPT_VIDEO ) ;
show_help_options ( options , " \n Advanced Video options: \n " ,
OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB ,
OPT_VIDEO | OPT_EXPERT ) ;
show_help_options ( options , " \n Audio options: \n " ,
OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB ,
OPT_AUDIO ) ;
show_help_options ( options , " \n Advanced Audio options: \n " ,
OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_GRAB ,
OPT_AUDIO | OPT_EXPERT ) ;
show_help_options ( options , " \n Subtitle options: \n " ,
OPT_SUBTITLE | OPT_GRAB ,
OPT_SUBTITLE ) ;
show_help_options ( options , " \n Audio/Video grab options: \n " ,
OPT_GRAB ,
OPT_GRAB ) ;
2008-05-31 20:36:44 +02:00
printf ( " \n " ) ;
2011-10-13 04:55:40 +02:00
show_help_children ( avcodec_get_class ( ) , flags ) ;
show_help_children ( avformat_get_class ( ) , flags ) ;
show_help_children ( sws_get_class ( ) , flags ) ;
2011-06-09 10:58:23 +02:00
2011-06-29 18:38:46 +02:00
return 0 ;
2007-11-15 13:31:58 +01:00
}
2011-09-05 02:04:27 +02:00
static int opt_target ( OptionsContext * o , const char * opt , const char * arg )
2003-11-03 18:28:44 +01:00
{
2009-12-15 00:18:49 +01:00
enum { PAL , NTSC , FILM , UNKNOWN } norm = UNKNOWN ;
2011-12-30 03:46:24 +01:00
static const char * const frame_rates [ ] = { " 25 " , " 30000/1001 " , " 24000/1001 " } ;
2003-11-03 18:28:44 +01:00
2011-12-30 03:46:24 +01:00
if ( ! strncmp ( arg , " pal- " , 4 ) ) {
2009-12-15 00:18:49 +01:00
norm = PAL ;
2003-11-03 18:28:44 +01:00
arg + = 4 ;
2011-12-30 03:46:24 +01:00
} else if ( ! strncmp ( arg , " ntsc- " , 5 ) ) {
2009-12-15 00:18:49 +01:00
norm = NTSC ;
2003-11-03 18:28:44 +01:00
arg + = 5 ;
2011-12-30 03:46:24 +01:00
} else if ( ! strncmp ( arg , " film- " , 5 ) ) {
2009-12-15 00:18:49 +01:00
norm = FILM ;
2004-12-19 16:31:55 +01:00
arg + = 5 ;
2003-11-03 18:28:44 +01:00
} else {
2011-09-11 23:35:35 +02:00
/* Try to determine PAL/NTSC by peeking in the input files */
2011-12-30 03:46:24 +01:00
if ( nb_input_files ) {
2011-09-11 23:35:35 +02:00
int i , j , fr ;
for ( j = 0 ; j < nb_input_files ; j + + ) {
for ( i = 0 ; i < input_files [ j ] . nb_streams ; i + + ) {
AVCodecContext * c = input_files [ j ] . ctx - > streams [ i ] - > codec ;
2011-12-30 03:46:24 +01:00
if ( c - > codec_type ! = AVMEDIA_TYPE_VIDEO )
2011-09-11 23:35:35 +02:00
continue ;
fr = c - > time_base . den * 1000 / c - > time_base . num ;
2011-12-30 03:46:24 +01:00
if ( fr = = 25000 ) {
2011-09-11 23:35:35 +02:00
norm = PAL ;
2003-11-03 18:28:44 +01:00
break ;
2011-12-30 03:46:24 +01:00
} else if ( ( fr = = 29970 ) | | ( fr = = 23976 ) ) {
2011-09-11 23:35:35 +02:00
norm = NTSC ;
2003-11-03 18:28:44 +01:00
break ;
2011-09-11 23:35:35 +02:00
}
2003-11-03 18:28:44 +01:00
}
2011-12-30 03:46:24 +01:00
if ( norm ! = UNKNOWN )
2011-09-11 23:35:35 +02:00
break ;
2003-11-03 18:28:44 +01:00
}
}
2011-09-27 02:14:37 +02:00
if ( norm ! = UNKNOWN )
av_log ( NULL , AV_LOG_INFO , " Assuming %s for target. \n " , norm = = PAL ? " PAL " : " NTSC " ) ;
2003-11-03 18:28:44 +01:00
}
2011-12-30 03:46:24 +01:00
if ( norm = = UNKNOWN ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " Could not determine norm (PAL/NTSC/NTSC-Film) for target. \n " ) ;
av_log ( NULL , AV_LOG_FATAL , " Please prefix target with \" pal- \" , \" ntsc- \" or \" film- \" , \n " ) ;
av_log ( NULL , AV_LOG_FATAL , " or set a framerate with \" -r xxx \" . \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2003-11-03 18:28:44 +01:00
}
2011-12-30 03:46:24 +01:00
if ( ! strcmp ( arg , " vcd " ) ) {
2011-09-05 22:10:26 +02:00
opt_video_codec ( o , " c:v " , " mpeg1video " ) ;
opt_audio_codec ( o , " c:a " , " mp2 " ) ;
2011-09-05 02:04:27 +02:00
parse_option ( o , " f " , " vcd " , options ) ;
2003-11-03 18:28:44 +01:00
2011-09-11 23:35:35 +02:00
parse_option ( o , " s " , norm = = PAL ? " 352x288 " : " 352x240 " , options ) ;
parse_option ( o , " r " , frame_rates [ norm ] , options ) ;
2009-12-16 00:25:16 +01:00
opt_default ( " g " , norm = = PAL ? " 15 " : " 18 " ) ;
2003-11-03 18:28:44 +01:00
2011-11-29 17:48:59 +01:00
opt_default ( " b:v " , " 1150000 " ) ;
2006-09-15 19:38:43 +02:00
opt_default ( " maxrate " , " 1150000 " ) ;
opt_default ( " minrate " , " 1150000 " ) ;
2006-09-18 21:27:12 +02:00
opt_default ( " bufsize " , " 327680 " ) ; // 40*1024*8;
2003-11-03 18:28:44 +01:00
2011-08-30 04:11:52 +02:00
opt_default ( " b:a " , " 224000 " ) ;
2011-09-11 23:35:35 +02:00
parse_option ( o , " ar " , " 44100 " , options ) ;
2011-09-10 20:52:48 +02:00
parse_option ( o , " ac " , " 2 " , options ) ;
2005-12-17 19:14:38 +01:00
2006-09-20 10:24:17 +02:00
opt_default ( " packetsize " , " 2324 " ) ;
2006-09-20 10:23:01 +02:00
opt_default ( " muxrate " , " 1411200 " ) ; // 2352 * 75 * 8;
2003-11-03 18:28:44 +01:00
2004-10-16 23:27:42 +02:00
/* We have to offset the PTS, so that it is consistent with the SCR.
SCR starts at 36000 , but the first two packs contain only padding
and the first pack from the other stream , respectively , may also have
been written before .
So the real data starts at SCR 36000 + 3 * 1200. */
2011-12-30 03:46:24 +01:00
o - > mux_preload = ( 36000 + 3 * 1200 ) / 90000.0 ; // 0.44
} else if ( ! strcmp ( arg , " svcd " ) ) {
2003-11-03 18:28:44 +01:00
2011-09-05 22:10:26 +02:00
opt_video_codec ( o , " c:v " , " mpeg2video " ) ;
opt_audio_codec ( o , " c:a " , " mp2 " ) ;
2011-09-05 02:04:27 +02:00
parse_option ( o , " f " , " svcd " , options ) ;
2003-11-03 18:28:44 +01:00
2011-09-11 23:35:35 +02:00
parse_option ( o , " s " , norm = = PAL ? " 480x576 " : " 480x480 " , options ) ;
parse_option ( o , " r " , frame_rates [ norm ] , options ) ;
parse_option ( o , " pix_fmt " , " yuv420p " , options ) ;
2009-12-16 00:25:16 +01:00
opt_default ( " g " , norm = = PAL ? " 15 " : " 18 " ) ;
2003-11-03 18:28:44 +01:00
2011-11-29 17:48:59 +01:00
opt_default ( " b:v " , " 2040000 " ) ;
2006-09-15 19:38:43 +02:00
opt_default ( " maxrate " , " 2516000 " ) ;
2011-12-30 03:46:24 +01:00
opt_default ( " minrate " , " 0 " ) ; // 1145000;
opt_default ( " bufsize " , " 1835008 " ) ; // 224*1024*8;
2008-09-13 19:25:38 +02:00
opt_default ( " flags " , " +scan_offset " ) ;
2005-09-12 12:23:52 +02:00
2003-11-03 18:28:44 +01:00
2011-08-30 04:11:52 +02:00
opt_default ( " b:a " , " 224000 " ) ;
2011-09-11 23:35:35 +02:00
parse_option ( o , " ar " , " 44100 " , options ) ;
2003-11-03 18:28:44 +01:00
2006-09-20 10:24:17 +02:00
opt_default ( " packetsize " , " 2324 " ) ;
2004-10-07 00:29:30 +02:00
2011-12-30 03:46:24 +01:00
} else if ( ! strcmp ( arg , " dvd " ) ) {
2003-11-03 18:28:44 +01:00
2011-09-05 22:10:26 +02:00
opt_video_codec ( o , " c:v " , " mpeg2video " ) ;
opt_audio_codec ( o , " c:a " , " ac3 " ) ;
2011-09-05 02:04:27 +02:00
parse_option ( o , " f " , " dvd " , options ) ;
2003-11-03 18:28:44 +01:00
2011-09-11 23:35:35 +02:00
parse_option ( o , " s " , norm = = PAL ? " 720x576 " : " 720x480 " , options ) ;
parse_option ( o , " r " , frame_rates [ norm ] , options ) ;
parse_option ( o , " pix_fmt " , " yuv420p " , options ) ;
2009-12-16 00:25:16 +01:00
opt_default ( " g " , norm = = PAL ? " 15 " : " 18 " ) ;
2003-11-03 18:28:44 +01:00
2011-11-29 17:48:59 +01:00
opt_default ( " b:v " , " 6000000 " ) ;
2006-09-15 19:38:43 +02:00
opt_default ( " maxrate " , " 9000000 " ) ;
2011-12-30 03:46:24 +01:00
opt_default ( " minrate " , " 0 " ) ; // 1500000;
opt_default ( " bufsize " , " 1835008 " ) ; // 224*1024*8;
2003-11-03 18:28:44 +01:00
2006-09-20 10:24:17 +02:00
opt_default ( " packetsize " , " 2048 " ) ; // from www.mpucoder.com: DVD sectors contain 2048 bytes of data, this is also the size of one pack.
2006-09-20 10:23:01 +02:00
opt_default ( " muxrate " , " 10080000 " ) ; // from mplex project: data_rate = 1260000. mux_rate = data_rate * 8
2004-11-21 04:37:33 +01:00
2011-08-30 04:11:52 +02:00
opt_default ( " b:a " , " 448000 " ) ;
2011-09-11 23:35:35 +02:00
parse_option ( o , " ar " , " 48000 " , options ) ;
2003-11-03 18:28:44 +01:00
2011-12-30 03:46:24 +01:00
} else if ( ! strncmp ( arg , " dv " , 2 ) ) {
2004-12-29 19:50:47 +01:00
2011-09-05 02:04:27 +02:00
parse_option ( o , " f " , " dv " , options ) ;
2004-12-29 19:50:47 +01:00
2011-09-11 23:35:35 +02:00
parse_option ( o , " s " , norm = = PAL ? " 720x576 " : " 720x480 " , options ) ;
parse_option ( o , " pix_fmt " , ! strncmp ( arg , " dv50 " , 4 ) ? " yuv422p " :
norm = = PAL ? " yuv420p " : " yuv411p " , options ) ;
parse_option ( o , " r " , frame_rates [ norm ] , options ) ;
2004-12-29 19:50:47 +01:00
2011-09-11 23:35:35 +02:00
parse_option ( o , " ar " , " 48000 " , options ) ;
2011-09-10 20:52:48 +02:00
parse_option ( o , " ac " , " 2 " , options ) ;
2004-12-29 19:50:47 +01:00
2003-11-03 18:28:44 +01:00
} else {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_ERROR , " Unknown target: %s \n " , arg ) ;
2011-05-24 18:14:42 +02:00
return AVERROR ( EINVAL ) ;
2003-11-03 18:28:44 +01:00
}
2011-05-24 18:14:42 +02:00
return 0 ;
2003-11-03 18:28:44 +01:00
}
2011-05-24 18:14:42 +02:00
static int opt_vstats_file ( const char * opt , const char * arg )
2007-04-25 15:55:11 +02:00
{
av_free ( vstats_filename ) ;
2011-12-30 03:46:24 +01:00
vstats_filename = av_strdup ( arg ) ;
2011-05-24 18:14:42 +02:00
return 0 ;
2007-04-25 15:55:11 +02:00
}
2011-05-24 18:14:42 +02:00
static int opt_vstats ( const char * opt , const char * arg )
2007-04-25 15:55:11 +02:00
{
char filename [ 40 ] ;
time_t today2 = time ( NULL ) ;
struct tm * today = localtime ( & today2 ) ;
snprintf ( filename , sizeof ( filename ) , " vstats_%02d%02d%02d.log " , today - > tm_hour , today - > tm_min ,
today - > tm_sec ) ;
2011-05-24 18:14:42 +02:00
return opt_vstats_file ( opt , filename ) ;
2007-04-25 15:55:11 +02:00
}
2011-09-05 22:10:26 +02:00
static int opt_video_frames ( OptionsContext * o , const char * opt , const char * arg )
2006-07-06 17:04:46 +02:00
{
2011-09-05 22:10:26 +02:00
return parse_option ( o , " frames:v " , arg , options ) ;
}
2006-07-06 17:04:46 +02:00
2011-09-05 22:10:26 +02:00
static int opt_audio_frames ( OptionsContext * o , const char * opt , const char * arg )
{
return parse_option ( o , " frames:a " , arg , options ) ;
}
2008-01-02 11:24:36 +01:00
2011-09-05 22:10:26 +02:00
static int opt_data_frames ( OptionsContext * o , const char * opt , const char * arg )
{
return parse_option ( o , " frames:d " , arg , options ) ;
2006-07-06 17:04:46 +02:00
}
2011-09-05 22:10:26 +02:00
static int opt_preset ( OptionsContext * o , const char * opt , const char * arg )
2011-09-02 23:49:07 +02:00
{
FILE * f = NULL ;
char filename [ 1000 ] , tmp [ 1000 ] , tmp2 [ 1000 ] , line [ 1000 ] ;
2011-09-12 12:02:41 +02:00
const char * codec_name = * opt = = ' v ' ? video_codec_name :
* opt = = ' a ' ? audio_codec_name :
subtitle_codec_name ;
2011-09-02 23:49:07 +02:00
if ( ! ( f = get_preset_file ( filename , sizeof ( filename ) , arg , * opt = = ' f ' , codec_name ) ) ) {
2011-09-26 22:02:13 +02:00
if ( ! strncmp ( arg , " libx264-lossless " , strlen ( " libx264-lossless " ) ) ) {
2011-09-27 02:14:37 +02:00
av_log ( 0 , AV_LOG_FATAL , " Please use -preset <speed> -qp 0 \n " ) ;
2011-09-26 22:02:13 +02:00
} else
2011-09-27 02:14:37 +02:00
av_log ( 0 , AV_LOG_FATAL , " File for preset '%s' not found \n " , arg ) ;
2011-09-02 23:49:07 +02:00
exit_program ( 1 ) ;
}
while ( ! feof ( f ) ) {
int e = fscanf ( f , " %999[^ \n ] \n " , line ) - 1 ;
if ( line [ 0 ] = = ' # ' & & ! e )
continue ;
e | = sscanf ( line , " %999[^=]=%999[^ \n ] \n " , tmp , tmp2 ) - 2 ;
if ( e ) {
2011-09-27 02:14:37 +02:00
av_log ( 0 , AV_LOG_FATAL , " %s: Invalid syntax: '%s' \n " , filename , line ) ;
2011-09-02 23:49:07 +02:00
exit_program ( 1 ) ;
}
if ( ! strcmp ( tmp , " acodec " ) ) {
2011-09-05 22:10:26 +02:00
opt_audio_codec ( o , tmp , tmp2 ) ;
2011-09-02 23:49:07 +02:00
} else if ( ! strcmp ( tmp , " vcodec " ) ) {
2011-09-05 22:10:26 +02:00
opt_video_codec ( o , tmp , tmp2 ) ;
2011-09-02 23:49:07 +02:00
} else if ( ! strcmp ( tmp , " scodec " ) ) {
2011-09-05 22:10:26 +02:00
opt_subtitle_codec ( o , tmp , tmp2 ) ;
2011-09-02 23:49:07 +02:00
} else if ( ! strcmp ( tmp , " dcodec " ) ) {
2011-09-05 22:10:26 +02:00
opt_data_codec ( o , tmp , tmp2 ) ;
2011-09-02 23:49:07 +02:00
} else if ( opt_default ( tmp , tmp2 ) < 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( 0 , AV_LOG_FATAL , " %s: Invalid option or argument: '%s', parsed as '%s' = '%s' \n " , filename , line , tmp , tmp2 ) ;
2011-09-02 23:49:07 +02:00
exit_program ( 1 ) ;
}
}
fclose ( f ) ;
return 0 ;
}
2011-09-12 11:44:14 +02:00
static void log_callback_null ( void * ptr , int level , const char * fmt , va_list vl )
2011-04-18 13:10:52 +02:00
{
}
2011-06-29 18:38:46 +02:00
static int opt_passlogfile ( const char * opt , const char * arg )
2011-04-21 00:46:20 +02:00
{
pass_logfilename_prefix = arg ;
2011-08-09 01:05:28 +02:00
# if CONFIG_LIBX264_ENCODER
2011-08-01 00:36:52 +02:00
return opt_default ( " passlogfile " , arg ) ;
2011-08-09 01:05:28 +02:00
# else
return 0 ;
# endif
2011-04-21 00:46:20 +02:00
}
2011-09-12 11:44:14 +02:00
static int opt_old2new ( OptionsContext * o , const char * opt , const char * arg )
{
2011-09-11 01:12:58 +02:00
char * s = av_malloc ( strlen ( opt ) + 2 ) ;
snprintf ( s , strlen ( opt ) + 2 , " %s:%c " , opt + 1 , * opt ) ;
return parse_option ( o , s , arg , options ) ;
}
2011-09-26 20:35:48 +02:00
static int opt_bitrate ( OptionsContext * o , const char * opt , const char * arg )
{
if ( ! strcmp ( opt , " b " ) ) {
2011-09-27 14:41:09 +02:00
av_log ( 0 , AV_LOG_WARNING , " Please use -b:a or -b:v, -b is ambiguous \n " ) ;
2011-09-26 20:35:48 +02:00
return parse_option ( o , av_strdup ( " b:v " ) , arg , options ) ;
}
return opt_default ( opt , arg ) ;
}
2011-09-11 23:35:35 +02:00
static int opt_video_filters ( OptionsContext * o , const char * opt , const char * arg )
{
return parse_option ( o , " filter:v " , arg , options ) ;
}
2011-09-11 01:12:58 +02:00
2012-01-05 02:03:12 +01:00
static int opt_vsync ( const char * opt , const char * arg )
{
if ( ! av_strcasecmp ( arg , " cfr " ) ) video_sync_method = VSYNC_CFR ;
else if ( ! av_strcasecmp ( arg , " vfr " ) ) video_sync_method = VSYNC_VFR ;
else if ( ! av_strcasecmp ( arg , " passthrough " ) ) video_sync_method = VSYNC_PASSTHROUGH ;
if ( video_sync_method = = VSYNC_AUTO )
video_sync_method = parse_number_or_die ( " vsync " , arg , OPT_INT , VSYNC_AUTO , VSYNC_VFR ) ;
return 0 ;
}
2011-09-05 02:04:27 +02:00
# define OFFSET(x) offsetof(OptionsContext, x)
2008-05-01 17:12:00 +02:00
static const OptionDef options [ ] = {
2003-08-24 17:29:48 +02:00
/* main options */
2009-11-30 00:12:19 +01:00
# include "cmdutils_common_opts.h"
2011-09-05 02:04:27 +02:00
{ " f " , HAS_ARG | OPT_STRING | OPT_OFFSET , { . off = OFFSET ( format ) } , " force format " , " fmt " } ,
{ " i " , HAS_ARG | OPT_FUNC2 , { ( void * ) opt_input_file } , " input file name " , " filename " } ,
2001-08-13 23:43:02 +02:00
{ " y " , OPT_BOOL , { ( void * ) & file_overwrite } , " overwrite output files " } ,
2011-11-24 21:42:42 +01:00
{ " n " , OPT_BOOL , { ( void * ) & no_file_overwrite } , " do not overwrite output files " } ,
2011-09-05 22:10:26 +02:00
{ " c " , HAS_ARG | OPT_STRING | OPT_SPEC , { . off = OFFSET ( codec_names ) } , " codec name " , " codec " } ,
{ " codec " , HAS_ARG | OPT_STRING | OPT_SPEC , { . off = OFFSET ( codec_names ) } , " codec name " , " codec " } ,
2011-10-18 01:33:09 +02:00
{ " pre " , HAS_ARG | OPT_STRING | OPT_SPEC , { . off = OFFSET ( presets ) } , " preset name " , " preset " } ,
2011-12-13 00:29:25 +01:00
{ " map " , HAS_ARG | OPT_EXPERT | OPT_FUNC2 , { ( void * ) opt_map } , " set input stream mapping " , " [-]input_file_id[:stream_specifier][,sync_file_id[:stream_specifier]] " } ,
2011-11-04 18:54:01 +01:00
{ " map_channel " , HAS_ARG | OPT_EXPERT | OPT_FUNC2 , { ( void * ) opt_map_channel } , " map an audio channel from one stream to another " , " file.stream.channel[:syncfile.syncstream] " } ,
2011-12-17 01:36:59 +01:00
{ " map_metadata " , HAS_ARG | OPT_STRING | OPT_SPEC , { . off = OFFSET ( metadata_map ) } , " set metadata information of outfile from infile " ,
2011-02-02 21:45:16 +01:00
" outfile[,metadata]:infile[,metadata] " } ,
2011-09-05 22:10:26 +02:00
{ " map_chapters " , OPT_INT | HAS_ARG | OPT_EXPERT | OPT_OFFSET , { . off = OFFSET ( chapters_input_file ) } , " set chapters mapping " , " input_file_index " } ,
2011-09-05 02:04:27 +02:00
{ " t " , HAS_ARG | OPT_TIME | OPT_OFFSET , { . off = OFFSET ( recording_time ) } , " record or transcode \" duration \" seconds of audio/video " , " duration " } ,
{ " fs " , HAS_ARG | OPT_INT64 | OPT_OFFSET , { . off = OFFSET ( limit_filesize ) } , " set the limit file size in bytes " , " limit_size " } , //
{ " ss " , HAS_ARG | OPT_TIME | OPT_OFFSET , { . off = OFFSET ( start_time ) } , " set the start time offset " , " time_off " } ,
{ " itsoffset " , HAS_ARG | OPT_TIME | OPT_OFFSET , { . off = OFFSET ( input_ts_offset ) } , " set the input ts offset " , " time_off " } ,
2011-09-05 22:10:26 +02:00
{ " itsscale " , HAS_ARG | OPT_DOUBLE | OPT_SPEC , { . off = OFFSET ( ts_scale ) } , " set the input ts scale " , " scale " } ,
{ " timestamp " , HAS_ARG | OPT_FUNC2 , { ( void * ) opt_recording_timestamp } , " set the recording timestamp ('now' to set the current time) " , " time " } ,
{ " metadata " , HAS_ARG | OPT_STRING | OPT_SPEC , { . off = OFFSET ( metadata ) } , " add metadata " , " string=string " } ,
{ " dframes " , HAS_ARG | OPT_FUNC2 , { ( void * ) opt_data_frames } , " set the number of data frames to record " , " number " } ,
2005-12-17 19:14:38 +01:00
{ " benchmark " , OPT_BOOL | OPT_EXPERT , { ( void * ) & do_benchmark } ,
2001-07-31 01:19:22 +02:00
" add timings for benchmarking " } ,
2011-05-24 18:14:42 +02:00
{ " timelimit " , HAS_ARG , { ( void * ) opt_timelimit } , " set max runtime in seconds " , " limit " } ,
2005-12-17 19:14:38 +01:00
{ " dump " , OPT_BOOL | OPT_EXPERT , { ( void * ) & do_pkt_dump } ,
2001-09-23 19:14:51 +02:00
" dump each input packet " } ,
2005-12-17 19:14:38 +01:00
{ " hex " , OPT_BOOL | OPT_EXPERT , { ( void * ) & do_hex_dump } ,
2003-11-10 19:54:17 +01:00
" when dumping packets, also dump the payload " } ,
2011-09-05 22:10:26 +02:00
{ " re " , OPT_BOOL | OPT_EXPERT | OPT_OFFSET , { . off = OFFSET ( rate_emu ) } , " read input at native frame rate " , " " } ,
2011-06-18 09:49:24 +02:00
{ " loop_input " , OPT_BOOL | OPT_EXPERT , { ( void * ) & loop_input } , " deprecated, use -loop " } ,
{ " loop_output " , HAS_ARG | OPT_INT | OPT_EXPERT , { ( void * ) & loop_output } , " deprecated, use -loop " , " " } ,
2011-09-05 02:04:27 +02:00
{ " target " , HAS_ARG | OPT_FUNC2 , { ( void * ) opt_target } , " specify target file type ( \" vcd \" , \" svcd \" , \" dvd \" , \" dv \" , \" dv50 \" , \" pal-vcd \" , \" ntsc-svcd \" , ...) " , " type " } ,
2012-01-05 02:03:12 +01:00
{ " vsync " , HAS_ARG | OPT_EXPERT , { ( void * ) opt_vsync } , " video sync method " , " " } ,
2004-06-30 16:47:29 +02:00
{ " async " , HAS_ARG | OPT_INT | OPT_EXPERT , { ( void * ) & audio_sync_method } , " audio sync method " , " " } ,
2008-04-08 03:01:00 +02:00
{ " adrift_threshold " , HAS_ARG | OPT_FLOAT | OPT_EXPERT , { ( void * ) & audio_drift_threshold } , " audio drift threshold " , " threshold " } ,
2004-06-12 05:41:36 +02:00
{ " copyts " , OPT_BOOL | OPT_EXPERT , { ( void * ) & copy_ts } , " copy timestamps " } ,
2011-12-01 04:32:27 +01:00
{ " copytb " , HAS_ARG | OPT_INT | OPT_EXPERT , { ( void * ) & copy_tb } , " copy input stream time base when stream copying " , " source " } ,
2005-03-23 01:52:31 +01:00
{ " shortest " , OPT_BOOL | OPT_EXPERT , { ( void * ) & opt_shortest } , " finish encoding within shortest input " } , //
2008-04-08 03:01:00 +02:00
{ " dts_delta_threshold " , HAS_ARG | OPT_FLOAT | OPT_EXPERT , { ( void * ) & dts_delta_threshold } , " timestamp discontinuity delta threshold " , " threshold " } ,
2008-09-05 01:23:44 +02:00
{ " xerror " , OPT_BOOL , { ( void * ) & exit_on_error } , " exit on error " , " error " } ,
2011-11-07 02:41:01 +01:00
{ " copyinkf " , OPT_BOOL | OPT_EXPERT | OPT_SPEC , { . off = OFFSET ( copy_initial_nonkeyframes ) } , " copy initial non-keyframes " } ,
2011-09-05 22:10:26 +02:00
{ " frames " , OPT_INT64 | HAS_ARG | OPT_SPEC , { . off = OFFSET ( max_frames ) } , " set the number of frames to record " , " number " } ,
2011-09-10 20:52:48 +02:00
{ " tag " , OPT_STRING | HAS_ARG | OPT_SPEC , { . off = OFFSET ( codec_tags ) } , " force codec tag/fourcc " , " fourcc/tag " } ,
2011-09-11 23:35:35 +02:00
{ " q " , HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC , { . off = OFFSET ( qscale ) } , " use fixed quality scale (VBR) " , " q " } ,
{ " qscale " , HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC , { . off = OFFSET ( qscale ) } , " use fixed quality scale (VBR) " , " q " } ,
# if CONFIG_AVFILTER
{ " filter " , HAS_ARG | OPT_STRING | OPT_SPEC , { . off = OFFSET ( filters ) } , " set stream filterchain " , " filter_list " } ,
# endif
2011-10-10 03:41:49 +02:00
{ " stats " , OPT_BOOL , { & print_stats } , " print progress report during encoding " , } ,
2011-11-04 01:44:06 +01:00
{ " attach " , HAS_ARG | OPT_FUNC2 , { ( void * ) opt_attach } , " add an attachment to the output file " , " filename " } ,
{ " dump_attachment " , HAS_ARG | OPT_STRING | OPT_SPEC , { . off = OFFSET ( dump_attachment ) } , " extract an attachment into a file " , " filename " } ,
2003-08-24 17:29:48 +02:00
/* video options */
2011-09-05 22:10:26 +02:00
{ " vframes " , HAS_ARG | OPT_VIDEO | OPT_FUNC2 , { ( void * ) opt_video_frames } , " set the number of video frames to record " , " number " } ,
2011-09-11 23:35:35 +02:00
{ " r " , HAS_ARG | OPT_VIDEO | OPT_STRING | OPT_SPEC , { . off = OFFSET ( frame_rates ) } , " set frame rate (Hz value, fraction or abbreviation) " , " rate " } ,
{ " s " , HAS_ARG | OPT_VIDEO | OPT_STRING | OPT_SPEC , { . off = OFFSET ( frame_sizes ) } , " set frame size (WxH or abbreviation) " , " size " } ,
{ " aspect " , HAS_ARG | OPT_VIDEO | OPT_STRING | OPT_SPEC , { . off = OFFSET ( frame_aspect_ratios ) } , " set aspect ratio (4:3, 16:9 or 1.3333, 1.7777) " , " aspect " } ,
{ " pix_fmt " , HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC , { . off = OFFSET ( frame_pix_fmts ) } , " set pixel format " , " format " } ,
2011-04-03 02:14:00 +02:00
{ " bits_per_raw_sample " , OPT_INT | HAS_ARG | OPT_VIDEO , { ( void * ) & frame_bits_per_raw_sample } , " set the number of bits per raw sample " , " number " } ,
2011-05-24 18:14:42 +02:00
{ " croptop " , HAS_ARG | OPT_VIDEO , { ( void * ) opt_frame_crop } , " Removed, use the crop filter instead " , " size " } ,
{ " cropbottom " , HAS_ARG | OPT_VIDEO , { ( void * ) opt_frame_crop } , " Removed, use the crop filter instead " , " size " } ,
{ " cropleft " , HAS_ARG | OPT_VIDEO , { ( void * ) opt_frame_crop } , " Removed, use the crop filter instead " , " size " } ,
{ " cropright " , HAS_ARG | OPT_VIDEO , { ( void * ) opt_frame_crop } , " Removed, use the crop filter instead " , " size " } ,
{ " padtop " , HAS_ARG | OPT_VIDEO , { ( void * ) opt_pad } , " Removed, use the pad filter instead " , " size " } ,
{ " padbottom " , HAS_ARG | OPT_VIDEO , { ( void * ) opt_pad } , " Removed, use the pad filter instead " , " size " } ,
{ " padleft " , HAS_ARG | OPT_VIDEO , { ( void * ) opt_pad } , " Removed, use the pad filter instead " , " size " } ,
{ " padright " , HAS_ARG | OPT_VIDEO , { ( void * ) opt_pad } , " Removed, use the pad filter instead " , " size " } ,
{ " padcolor " , HAS_ARG | OPT_VIDEO , { ( void * ) opt_pad } , " Removed, use the pad filter instead " , " color " } ,
2003-08-24 17:29:48 +02:00
{ " intra " , OPT_BOOL | OPT_EXPERT | OPT_VIDEO , { ( void * ) & intra_only } , " use only intra frames " } ,
2011-09-10 20:52:48 +02:00
{ " vn " , OPT_BOOL | OPT_VIDEO | OPT_OFFSET , { . off = OFFSET ( video_disable ) } , " disable video " } ,
2005-03-17 06:07:54 +01:00
{ " vdt " , OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO , { ( void * ) & video_discard } , " discard threshold " , " n " } ,
2011-09-11 23:35:35 +02:00
{ " rc_override " , HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC , { . off = OFFSET ( rc_overrides ) } , " rate control override for specific intervals " , " override " } ,
2011-09-05 22:10:26 +02:00
{ " vcodec " , HAS_ARG | OPT_VIDEO | OPT_FUNC2 , { ( void * ) opt_video_codec } , " force video codec ('copy' to copy stream) " , " codec " } ,
2011-08-30 01:46:34 +02:00
{ " sameq " , OPT_BOOL | OPT_VIDEO , { ( void * ) & same_quant } , " use same quantizer as source (implies VBR) " } ,
2011-09-11 23:35:35 +02:00
{ " same_quant " , OPT_BOOL | OPT_VIDEO , { ( void * ) & same_quant } ,
2011-04-09 13:50:05 +02:00
" use same quantizer as source (implies VBR) " } ,
2011-05-24 18:14:42 +02:00
{ " pass " , HAS_ARG | OPT_VIDEO , { ( void * ) opt_pass } , " select the pass number (1 or 2) " , " n " } ,
2011-04-21 00:46:20 +02:00
{ " passlogfile " , HAS_ARG | OPT_VIDEO , { ( void * ) & opt_passlogfile } , " select two pass log file name prefix " , " prefix " } ,
2005-12-17 19:14:38 +01:00
{ " deinterlace " , OPT_BOOL | OPT_EXPERT | OPT_VIDEO , { ( void * ) & do_deinterlace } ,
2003-08-24 17:29:48 +02:00
" deinterlace pictures " } ,
2011-11-09 18:58:07 +01:00
{ " psnr " , OPT_BOOL | OPT_EXPERT | OPT_VIDEO , { ( void * ) & do_psnr } , " calculate PSNR of compressed frames " } ,
2007-04-25 15:55:11 +02:00
{ " vstats " , OPT_EXPERT | OPT_VIDEO , { ( void * ) & opt_vstats } , " dump video coding statistics to file " } ,
{ " vstats_file " , HAS_ARG | OPT_EXPERT | OPT_VIDEO , { ( void * ) opt_vstats_file } , " dump video coding statistics to file " , " file " } ,
2010-05-07 11:43:21 +02:00
# if CONFIG_AVFILTER
2011-09-11 23:35:35 +02:00
{ " vf " , HAS_ARG | OPT_VIDEO | OPT_FUNC2 , { ( void * ) opt_video_filters } , " video filters " , " filter list " } ,
2010-05-07 11:43:21 +02:00
# endif
2011-09-11 23:35:35 +02:00
{ " intra_matrix " , HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC , { . off = OFFSET ( intra_matrices ) } , " specify intra matrix coeffs " , " matrix " } ,
{ " inter_matrix " , HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC , { . off = OFFSET ( inter_matrices ) } , " specify inter matrix coeffs " , " matrix " } ,
{ " top " , HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_INT | OPT_SPEC , { . off = OFFSET ( top_field_first ) } , " top=1/bottom=0/auto=-1 field first " , " " } ,
2004-04-30 15:44:29 +02:00
{ " dc " , OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO , { ( void * ) & intra_dc_precision } , " intra_dc_precision " , " precision " } ,
2011-09-11 01:15:36 +02:00
{ " vtag " , HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_FUNC2 , { ( void * ) opt_old2new } , " force video tag/fourcc " , " fourcc/tag " } ,
2005-12-18 21:01:02 +01:00
{ " qphist " , OPT_BOOL | OPT_EXPERT | OPT_VIDEO , { ( void * ) & qp_hist } , " show QP histogram " } ,
2011-09-11 23:35:35 +02:00
{ " force_fps " , OPT_BOOL | OPT_EXPERT | OPT_VIDEO | OPT_SPEC , { . off = OFFSET ( force_fps ) } , " force the selected framerate, disable the best supported framerate selection " } ,
{ " streamid " , HAS_ARG | OPT_EXPERT | OPT_FUNC2 , { ( void * ) opt_streamid } , " set the value of an outfile streamid " , " streamIndex:value " } ,
{ " force_key_frames " , OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_SPEC , { . off = OFFSET ( forced_key_frames ) } , " force key frames at specified timestamps " , " timestamps " } ,
2011-09-26 20:35:48 +02:00
{ " b " , HAS_ARG | OPT_VIDEO | OPT_FUNC2 , { ( void * ) opt_bitrate } , " video bitrate (please use -b:v) " , " bitrate " } ,
2003-08-24 17:29:48 +02:00
/* audio options */
2011-09-05 22:10:26 +02:00
{ " aframes " , HAS_ARG | OPT_AUDIO | OPT_FUNC2 , { ( void * ) opt_audio_frames } , " set the number of audio frames to record " , " number " } ,
2011-09-11 23:35:35 +02:00
{ " aq " , HAS_ARG | OPT_AUDIO | OPT_FUNC2 , { ( void * ) opt_audio_qscale } , " set audio quality (codec-specific) " , " quality " , } ,
{ " ar " , HAS_ARG | OPT_AUDIO | OPT_INT | OPT_SPEC , { . off = OFFSET ( audio_sample_rate ) } , " set audio sampling rate (in Hz) " , " rate " } ,
2011-09-10 20:52:48 +02:00
{ " ac " , HAS_ARG | OPT_AUDIO | OPT_INT | OPT_SPEC , { . off = OFFSET ( audio_channels ) } , " set number of audio channels " , " channels " } ,
{ " an " , OPT_BOOL | OPT_AUDIO | OPT_OFFSET , { . off = OFFSET ( audio_disable ) } , " disable audio " } ,
2011-09-05 22:10:26 +02:00
{ " acodec " , HAS_ARG | OPT_AUDIO | OPT_FUNC2 , { ( void * ) opt_audio_codec } , " force audio codec ('copy' to copy stream) " , " codec " } ,
2011-09-11 01:15:36 +02:00
{ " atag " , HAS_ARG | OPT_EXPERT | OPT_AUDIO | OPT_FUNC2 , { ( void * ) opt_old2new } , " force audio tag/fourcc " , " fourcc/tag " } ,
2005-03-23 03:10:23 +01:00
{ " vol " , OPT_INT | HAS_ARG | OPT_AUDIO , { ( void * ) & audio_volume } , " change audio volume (256=normal) " , " volume " } , //
2011-09-11 23:35:35 +02:00
{ " sample_fmt " , HAS_ARG | OPT_EXPERT | OPT_AUDIO | OPT_SPEC | OPT_STRING , { . off = OFFSET ( sample_fmts ) } , " set sample format " , " format " } ,
2011-10-26 00:45:52 +02:00
{ " rmvol " , HAS_ARG | OPT_AUDIO | OPT_FLOAT | OPT_SPEC , { . off = OFFSET ( rematrix_volume ) } , " rematrix volume (as factor) " , " volume " } ,
2003-08-24 17:29:48 +02:00
2005-06-03 16:31:45 +02:00
/* subtitle options */
2011-09-10 20:52:48 +02:00
{ " sn " , OPT_BOOL | OPT_SUBTITLE | OPT_OFFSET , { . off = OFFSET ( subtitle_disable ) } , " disable subtitle " } ,
2011-09-05 22:10:26 +02:00
{ " scodec " , HAS_ARG | OPT_SUBTITLE | OPT_FUNC2 , { ( void * ) opt_subtitle_codec } , " force subtitle codec ('copy' to copy stream) " , " codec " } ,
2011-09-11 01:15:36 +02:00
{ " stag " , HAS_ARG | OPT_EXPERT | OPT_SUBTITLE | OPT_FUNC2 , { ( void * ) opt_old2new } , " force subtitle tag/fourcc " , " fourcc/tag " } ,
2005-12-17 19:14:38 +01:00
2003-08-24 17:29:48 +02:00
/* grab options */
2011-06-15 07:34:12 +02:00
{ " vc " , HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB , { ( void * ) opt_video_channel } , " deprecated, use -channel " , " channel " } ,
{ " tvstd " , HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB , { ( void * ) opt_video_standard } , " deprecated, use -standard " , " standard " } ,
2007-02-14 18:01:32 +01:00
{ " isync " , OPT_BOOL | OPT_EXPERT | OPT_GRAB , { ( void * ) & input_sync } , " sync read on input " , " " } ,
2005-12-17 19:14:38 +01:00
/* muxer options */
2011-09-05 22:10:26 +02:00
{ " muxdelay " , OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET , { . off = OFFSET ( mux_max_delay ) } , " set the maximum demux-decode delay " , " seconds " } ,
{ " muxpreload " , OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET , { . off = OFFSET ( mux_preload ) } , " set the initial demux-decode delay " , " seconds " } ,
2006-07-06 17:04:46 +02:00
2011-09-05 22:10:26 +02:00
{ " bsf " , HAS_ARG | OPT_STRING | OPT_SPEC , { . off = OFFSET ( bitstream_filters ) } , " A comma-separated list of bitstream filters " , " bitstream_filters " } ,
2011-09-11 01:12:58 +02:00
{ " absf " , HAS_ARG | OPT_AUDIO | OPT_EXPERT | OPT_FUNC2 , { ( void * ) opt_old2new } , " deprecated " , " audio bitstream_filters " } ,
{ " vbsf " , HAS_ARG | OPT_VIDEO | OPT_EXPERT | OPT_FUNC2 , { ( void * ) opt_old2new } , " deprecated " , " video bitstream_filters " } ,
2006-07-06 17:04:46 +02:00
2011-09-05 22:10:26 +02:00
{ " apre " , HAS_ARG | OPT_AUDIO | OPT_EXPERT | OPT_FUNC2 , { ( void * ) opt_preset } , " set the audio options to the indicated preset " , " preset " } ,
{ " vpre " , HAS_ARG | OPT_VIDEO | OPT_EXPERT | OPT_FUNC2 , { ( void * ) opt_preset } , " set the video options to the indicated preset " , " preset " } ,
{ " spre " , HAS_ARG | OPT_SUBTITLE | OPT_EXPERT | OPT_FUNC2 , { ( void * ) opt_preset } , " set the subtitle options to the indicated preset " , " preset " } ,
{ " fpre " , HAS_ARG | OPT_EXPERT | OPT_FUNC2 , { ( void * ) opt_preset } , " set options from indicated preset file " , " filename " } ,
2011-04-14 13:32:36 +02:00
/* data codec support */
2011-09-05 22:10:26 +02:00
{ " dcodec " , HAS_ARG | OPT_DATA | OPT_FUNC2 , { ( void * ) opt_data_codec } , " force data codec ('copy' to copy stream) " , " codec " } ,
2011-12-01 18:02:04 +01:00
{ " dn " , OPT_BOOL | OPT_VIDEO | OPT_OFFSET , { . off = OFFSET ( data_disable ) } , " disable data " } ,
2008-06-07 11:12:42 +02:00
2011-05-24 18:14:42 +02:00
{ " default " , HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT , { ( void * ) opt_default } , " generic catch all option " , " " } ,
2001-07-22 16:37:44 +02:00
{ NULL , } ,
} ;
2007-09-16 20:08:51 +02:00
int main ( int argc , char * * argv )
{
2011-09-05 02:04:27 +02:00
OptionsContext o = { 0 } ;
2007-09-16 20:08:51 +02:00
int64_t ti ;
2011-09-05 03:11:18 +02:00
reset_options ( & o , 0 ) ;
2011-09-05 02:04:27 +02:00
2010-09-24 17:39:10 +02:00
av_log_set_flags ( AV_LOG_SKIP_REPEATED ) ;
2011-09-26 08:15:37 +02:00
parse_loglevel ( argc , argv , options ) ;
2010-09-24 17:39:10 +02:00
2011-04-18 13:10:52 +02:00
if ( argc > 1 & & ! strcmp ( argv [ 1 ] , " -d " ) ) {
2011-04-22 18:49:44 +02:00
run_as_daemon = 1 ;
2011-04-18 13:10:52 +02:00
av_log_set_callback ( log_callback_null ) ;
argc - - ;
argv + + ;
}
2007-11-22 17:10:02 +01:00
avcodec_register_all ( ) ;
2010-04-22 10:55:23 +02:00
# if CONFIG_AVDEVICE
2007-11-22 17:10:02 +01:00
avdevice_register_all ( ) ;
2010-05-07 11:43:21 +02:00
# endif
# if CONFIG_AVFILTER
avfilter_register_all ( ) ;
2010-04-22 10:55:23 +02:00
# endif
2007-09-16 20:08:51 +02:00
av_register_all ( ) ;
2011-11-06 01:47:48 +01:00
avformat_network_init ( ) ;
2007-09-16 20:08:51 +02:00
2011-12-20 22:03:25 +01:00
show_banner ( argc , argv , options ) ;
2007-09-16 20:08:51 +02:00
2011-10-08 17:20:52 +02:00
term_init ( ) ;
2007-09-16 20:08:51 +02:00
/* parse options */
2011-09-05 02:04:27 +02:00
parse_options ( & o , argc , argv , options , opt_output_file ) ;
2007-09-16 20:08:51 +02:00
2011-12-30 03:46:24 +01:00
if ( nb_output_files < = 0 & & nb_input_files = = 0 ) {
2009-12-21 03:15:46 +01:00
show_usage ( ) ;
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_WARNING , " Use -h to get full help or, even better, run 'man %s' \n " , program_name ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2009-12-21 03:15:46 +01:00
}
2009-12-13 14:49:14 +01:00
2007-09-16 20:08:51 +02:00
/* file converter / grab */
if ( nb_output_files < = 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " At least one output file must be specified \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2007-09-16 20:08:51 +02:00
}
if ( nb_input_files = = 0 ) {
2011-09-27 02:14:37 +02:00
av_log ( NULL , AV_LOG_FATAL , " At least one input file must be specified \n " ) ;
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2007-09-16 20:08:51 +02:00
}
ti = getutime ( ) ;
2011-08-30 04:05:20 +02:00
if ( transcode ( output_files , nb_output_files , input_files , nb_input_files ) < 0 )
2011-08-30 01:11:54 +02:00
exit_program ( 1 ) ;
2007-09-16 20:08:51 +02:00
ti = getutime ( ) - ti ;
if ( do_benchmark ) {
2010-02-22 23:21:58 +01:00
int maxrss = getmaxrss ( ) / 1024 ;
printf ( " bench: utime=%0.3fs maxrss=%ikB \n " , ti / 1000000.0 , maxrss ) ;
2007-09-16 20:08:51 +02:00
}
2011-08-29 07:03:24 +02:00
exit_program ( 0 ) ;
return 0 ;
2007-09-16 20:08:51 +02:00
}