#include "fifo.h"
#include "avstring.h"
-#ifdef __MINGW32__
-#include <conio.h>
-#else
+#if !defined(HAVE_GETRUSAGE) && defined(HAVE_GETPROCESSTIMES)
+#include <windows.h>
+#endif
+
+#if defined(HAVE_TERMIOS_H)
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <termios.h>
#include <sys/resource.h>
-#endif
-#ifdef CONFIG_OS2
-#include <sys/types.h>
-#include <sys/select.h>
-#include <stdlib.h>
+#elif defined(HAVE_CONIO_H)
+#include <conio.h>
#endif
#undef time //needed because HAVE_AV_CONFIG_H is defined on top
#include <time.h>
extern const OptionDef options[];
static void show_help(void);
-static void show_license(void);
+static void opt_show_license(void);
static int opt_default(const char *opt, const char *arg);
#define MAX_FILES 20
#endif
static char *video_rc_override_string=NULL;
static char *video_rc_eq="tex^qComp";
-static int me_method = ME_EPZS;
static int video_disable = 0;
static int video_discard = 0;
-static int video_codec_id = CODEC_ID_NONE;
+static char *video_codec_name = NULL;
static int video_codec_tag = 0;
static int same_quality = 0;
static int do_deinterlace = 0;
static float audio_qscale = QSCALE_NONE;
static int audio_disable = 0;
static int audio_channels = 1;
-static int audio_codec_id = CODEC_ID_NONE;
+static char *audio_codec_name = NULL;
static int audio_codec_tag = 0;
static char *audio_language = NULL;
-static int subtitle_codec_id = CODEC_ID_NONE;
+static int subtitle_disable = 0;
+static char *subtitle_codec_name = NULL;
static char *subtitle_language = NULL;
static float mux_preload= 0.5;
static int subtitle_stream_copy = 0;
static int video_sync_method= 1;
static int audio_sync_method= 0;
+static float audio_drift_threshold= 0.1;
static int copy_ts= 0;
static int opt_shortest = 0; //
static int video_global_header = 0;
static char *vstats_filename;
-static FILE *fvstats;
+static FILE *vstats_file;
static int rate_emu = 0;
static uint64_t limit_filesize = 0; //
static int pgmyuv_compatibility_hack=0;
-static int dts_delta_threshold = 10;
+static float dts_delta_threshold = 10;
static int sws_flags = SWS_BICUBIC;
int nb_streams; /* nb streams we are aware of */
} AVInputFile;
-#ifndef __MINGW32__
+#ifdef HAVE_TERMIOS_H
/* init terminal so that we can grab keys */
static struct termios oldtty;
static void term_exit(void)
{
-#ifndef __MINGW32__
+#ifdef HAVE_TERMIOS_H
tcsetattr (0, TCSANOW, &oldtty);
#endif
}
static void term_init(void)
{
-#ifndef __MINGW32__
+#ifdef HAVE_TERMIOS_H
struct termios tty;
tcgetattr (0, &tty);
/* read a key without blocking */
static int read_key(void)
{
-#ifdef __MINGW32__
- if(kbhit())
- return(getch());
-#else
+#if defined(HAVE_TERMIOS_H)
int n = 1;
unsigned char ch;
#ifndef CONFIG_BEOS_NETSERVER
return n;
}
+#elif defined(HAVE_CONIO_H)
+ if(kbhit())
+ return(getch());
#endif
return -1;
}
get_sync_ipts(const AVOutputStream *ost)
{
const AVInputStream *ist = ost->sync_ist;
- return (double)(ist->pts + input_files_ts_offset[ist->file_index] - start_time)/AV_TIME_BASE;
+ return (double)(ist->pts - start_time)/AV_TIME_BASE;
}
static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx, AVBitStreamFilterContext *bsfc){
//FIXME resample delay
if(fabs(delta) > 50){
- if(ist->is_start){
+ if(ist->is_start || fabs(delta) > audio_drift_threshold*enc->sample_rate){
if(byte_delta < 0){
byte_delta= FFMAX(byte_delta, -size);
size += byte_delta;
picture2 = picture;
}
- frame_hook_process(picture2, dec->pix_fmt, dec->width, dec->height,
- 1000000 * ist->pts / AV_TIME_BASE);
+ if (ENABLE_VHOOK)
+ frame_hook_process(picture2, dec->pix_fmt, dec->width, dec->height,
+ 1000000 * ist->pts / AV_TIME_BASE);
if (picture != picture2)
*picture = *picture2;
pkt.stream_index = ost->index;
pkt.data = subtitle_out;
pkt.size = subtitle_out_size;
- pkt.pts = av_rescale_q(av_rescale_q(pts, ist->st->time_base, AV_TIME_BASE_Q) + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ost->st->time_base);
+ pkt.pts = av_rescale_q(pts, ist->st->time_base, ost->st->time_base);
if (enc->codec_id == CODEC_ID_DVB_SUBTITLE) {
/* XXX: the pts correction is handled here. Maybe handling
it in the codec would be better */
{
AVCodecContext *enc;
int frame_number;
- int64_t ti;
double ti1, bitrate, avg_bitrate;
/* this is executed just the first time do_video_stats is called */
- if (!fvstats) {
- fvstats = fopen(vstats_filename, "w");
- if (!fvstats) {
+ if (!vstats_file) {
+ vstats_file = fopen(vstats_filename, "w");
+ if (!vstats_file) {
perror("fopen");
exit(1);
}
}
- ti = INT64_MAX;
enc = ost->st->codec;
if (enc->codec_type == CODEC_TYPE_VIDEO) {
frame_number = ost->frame_number;
- fprintf(fvstats, "frame= %5d q= %2.1f ", frame_number, enc->coded_frame->quality/(float)FF_QP2LAMBDA);
+ fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, enc->coded_frame->quality/(float)FF_QP2LAMBDA);
if (enc->flags&CODEC_FLAG_PSNR)
- fprintf(fvstats, "PSNR= %6.2f ", psnr(enc->coded_frame->error[0]/(enc->width*enc->height*255.0*255.0)));
+ fprintf(vstats_file, "PSNR= %6.2f ", psnr(enc->coded_frame->error[0]/(enc->width*enc->height*255.0*255.0)));
- fprintf(fvstats,"f_size= %6d ", frame_size);
+ fprintf(vstats_file,"f_size= %6d ", frame_size);
/* compute pts value */
ti1 = ost->sync_opts * av_q2d(enc->time_base);
if (ti1 < 0.01)
bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0;
avg_bitrate = (double)(video_size * 8) / ti1 / 1000.0;
- fprintf(fvstats, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
+ fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
(double)video_size / 1024, ti1, bitrate, avg_bitrate);
- fprintf(fvstats,"type= %c\n", av_get_pict_type_char(enc->coded_frame->pict_type));
+ fprintf(vstats_file,"type= %c\n", av_get_pict_type_char(enc->coded_frame->pict_type));
}
}
vid = 1;
}
/* compute min output value */
- pts = (double)ost->st->pts.val * ost->st->time_base.num / ost->st->time_base.den;
+ pts = (double)ost->st->pts.val * av_q2d(ost->st->time_base);
if ((pts < ti1) && (pts > 0))
ti1 = pts;
}
AVPacket opkt;
av_init_packet(&opkt);
+ if (!ost->frame_number && !(pkt->flags & PKT_FLAG_KEY))
+ continue;
+
/* no reencoding needed : output the packet directly */
/* force the input stream PTS */
opkt.stream_index= ost->index;
if(pkt->pts != AV_NOPTS_VALUE)
- opkt.pts= av_rescale_q(av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q) + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ost->st->time_base);
+ opkt.pts= av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base);
else
opkt.pts= AV_NOPTS_VALUE;
- {
- int64_t dts;
if (pkt->dts == AV_NOPTS_VALUE)
- dts = ist->next_pts;
+ opkt.dts = av_rescale_q(ist->next_pts, AV_TIME_BASE_Q, ost->st->time_base);
else
- dts= av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
- opkt.dts= av_rescale_q(dts + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ost->st->time_base);
- }
+ opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
+
+ opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base);
opkt.flags= pkt->flags;
//FIXME remove the following 2 lines they shall be replaced by the bitstream filters
return -1;
}
+static void print_sdp(AVFormatContext **avc, int n)
+{
+ char sdp[2048];
+
+ avf_sdp_create(avc, n, sdp, sizeof(sdp));
+ printf("SDP:\n%s\n", sdp);
+}
/*
* The following code is the main loop of the file converter
AVInputStream *ist, **ist_table = NULL;
AVInputFile *file_table;
int key;
+ int want_sdp = 1;
file_table= (AVInputFile*) av_mallocz(nb_input_files * sizeof(AVInputFile));
if (!file_table)
/* for each output stream, we compute the right encoding parameters */
for(i=0;i<nb_ostreams;i++) {
ost = ost_table[i];
+ os = output_files[ost->file_index];
ist = ist_table[ost->source_index];
codec = ost->st->codec;
icodec = ist->st->codec;
+ if (!ost->st->language[0])
+ av_strlcpy(ost->st->language, ist->st->language,
+ sizeof(ost->st->language));
+
if (ost->st->stream_copy) {
/* if stream_copy is selected, no need to decode or encode */
codec->codec_id = icodec->codec_id;
codec->codec_type = icodec->codec_type;
- if(!codec->codec_tag) codec->codec_tag = icodec->codec_tag;
+
+ if(!codec->codec_tag){
+ if( !os->oformat->codec_tag
+ || av_codec_get_id (os->oformat->codec_tag, icodec->codec_tag) > 0
+ || av_codec_get_tag(os->oformat->codec_tag, icodec->codec_id) <= 0)
+ codec->codec_tag = icodec->codec_tag;
+ }
+
codec->bit_rate = icodec->bit_rate;
codec->extradata= icodec->extradata;
codec->extradata_size= icodec->extradata_size;
codec->channels = icodec->channels;
codec->frame_size = icodec->frame_size;
codec->block_align= icodec->block_align;
+ if(codec->block_align == 1 && codec->codec_id == CODEC_ID_MP3)
+ codec->block_align= 0;
break;
case CODEC_TYPE_VIDEO:
if(using_vhook) {
ist = ist_table[i];
is = input_files[ist->file_index];
ist->pts = 0;
- ist->next_pts = av_rescale_q(ist->st->start_time, ist->st->time_base, AV_TIME_BASE_Q);
- if(ist->st->start_time == AV_NOPTS_VALUE)
- ist->next_pts=0;
- if(input_files_ts_offset[ist->file_index])
+ ist->next_pts=0;
+ if( input_files_ts_offset[ist->file_index] != -is->start_time
+ && !(is->start_time == AV_NOPTS_VALUE && input_files_ts_offset[ist->file_index]==0))
ist->next_pts= AV_NOPTS_VALUE;
ist->is_start = 1;
}
ret = AVERROR(EINVAL);
goto fail;
}
+ if (strcmp(output_files[i]->oformat->name, "rtp")) {
+ want_sdp = 0;
+ }
+ }
+ if (want_sdp) {
+ print_sdp(output_files, nb_output_files);
}
if ( !using_stdin && verbose >= 0) {
is = input_files[file_index];
if (av_read_frame(is, &pkt) < 0) {
file_table[file_index].eof_reached = 1;
- if (opt_shortest) break; else continue; //
+ if (opt_shortest)
+ break;
+ else
+ continue;
}
if (do_pkt_dump) {
if (ist->discard)
goto discard_packet;
+ if (pkt.dts != AV_NOPTS_VALUE)
+ pkt.dts += av_rescale_q(input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ist->st->time_base);
+ if (pkt.pts != AV_NOPTS_VALUE)
+ pkt.pts += av_rescale_q(input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ist->st->time_base);
+
// fprintf(stderr, "next:%"PRId64" dts:%"PRId64" off:%"PRId64" %d\n", ist->next_pts, pkt.dts, input_files_ts_offset[ist->file_index], ist->st->codec->codec_type);
if (pkt.dts != AV_NOPTS_VALUE && ist->next_pts != AV_NOPTS_VALUE) {
- int64_t delta= av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q) - ist->next_pts;
- if(FFABS(delta) > 1LL*dts_delta_threshold*AV_TIME_BASE && !copy_ts){
+ 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;
+ if((FFABS(delta) > 1LL*dts_delta_threshold*AV_TIME_BASE || pkt_dts+1<ist->pts)&& !copy_ts){
input_files_ts_offset[ist->file_index]-= delta;
if (verbose > 2)
fprintf(stderr, "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", delta, input_files_ts_offset[ist->file_index]);
- for(i=0; i<file_table[file_index].nb_streams; i++){
- int index= file_table[file_index].ist_index + i;
- ist_table[index]->next_pts += delta;
- ist_table[index]->is_start=1;
- }
+ pkt.dts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
+ if(pkt.pts != AV_NOPTS_VALUE)
+ pkt.pts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
}
}
video_standard = av_strdup(arg);
}
-static void opt_codec(int *pstream_copy, int *pcodec_id,
+static void opt_codec(int *pstream_copy, char **pcodec_name,
int codec_type, const char *arg)
{
- AVCodec *p;
-
+ av_freep(pcodec_name);
if (!strcmp(arg, "copy")) {
*pstream_copy = 1;
} else {
- p = first_avcodec;
- while (p) {
- if (!strcmp(p->name, arg) && p->type == codec_type)
- break;
- p = p->next;
- }
- if (p == NULL) {
- fprintf(stderr, "Unknown codec '%s'\n", arg);
- exit(1);
- } else {
- *pcodec_id = p->id;
- }
+ *pcodec_name = av_strdup(arg);
}
}
static void opt_audio_codec(const char *arg)
{
- opt_codec(&audio_stream_copy, &audio_codec_id, CODEC_TYPE_AUDIO, arg);
+ opt_codec(&audio_stream_copy, &audio_codec_name, CODEC_TYPE_AUDIO, arg);
}
static void opt_audio_tag(const char *arg)
video_codec_tag= arg[0] + (arg[1]<<8) + (arg[2]<<16) + (arg[3]<<24);
}
+#ifdef CONFIG_VHOOK
static void add_frame_hooker(const char *arg)
{
int argc = 0;
exit(1);
}
}
-
-const char *motion_str[] = {
- "zero",
- "full",
- "log",
- "phods",
- "epzs",
- "x1",
- "hex",
- "umh",
- "iter",
- NULL,
-};
-
-static void opt_motion_estimation(const char *arg)
-{
- const char **p;
- p = motion_str;
- for(;;) {
- if (!*p) {
- fprintf(stderr, "Unknown motion estimation method '%s'\n", arg);
- exit(1);
- }
- if (!strcmp(*p, arg))
- break;
- p++;
- }
- me_method = (p - motion_str) + 1;
-}
+#endif
static void opt_video_codec(const char *arg)
{
- opt_codec(&video_stream_copy, &video_codec_id, CODEC_TYPE_VIDEO, arg);
+ opt_codec(&video_stream_copy, &video_codec_name, CODEC_TYPE_VIDEO, arg);
}
static void opt_subtitle_codec(const char *arg)
{
- opt_codec(&subtitle_stream_copy, &subtitle_codec_id, CODEC_TYPE_SUBTITLE, arg);
+ opt_codec(&subtitle_stream_copy, &subtitle_codec_name, CODEC_TYPE_SUBTITLE, arg);
}
static void opt_map(const char *arg)
input_ts_offset = parse_date(arg, 1);
}
+static enum CodecID find_codec_or_die(const char *name, int type, int encoder)
+{
+ char *codec_string = encoder ? "encoder" : "decoder";
+ AVCodec *codec;
+
+ if(!name)
+ return CODEC_ID_NONE;
+ codec = encoder ?
+ avcodec_find_encoder_by_name(name) :
+ avcodec_find_decoder_by_name(name);
+ if(!codec) {
+ av_log(NULL, AV_LOG_ERROR, "Unknown %s '%s'\n", codec_string, name);
+ exit(1);
+ }
+ if(codec->type != type) {
+ av_log(NULL, AV_LOG_ERROR, "Invalid %s type '%s'\n", codec_string, name);
+ exit(1);
+ }
+ return codec->id;
+}
+
static void opt_input_file(const char *filename)
{
AVFormatContext *ic;
ap->pix_fmt = frame_pix_fmt;
ap->channel = video_channel;
ap->standard = video_standard;
- ap->video_codec_id = video_codec_id;
- ap->audio_codec_id = audio_codec_id;
+ ap->video_codec_id = find_codec_or_die(video_codec_name, CODEC_TYPE_VIDEO, 0);
+ ap->audio_codec_id = find_codec_or_die(audio_codec_name, CODEC_TYPE_AUDIO, 0);
if(pgmyuv_compatibility_hack)
ap->video_codec_id= CODEC_ID_PGMYUV;
for(i=0; i<opt_name_count; i++){
const AVOption *opt;
double d= av_get_double(avformat_opts, opt_names[i], &opt);
- if(d==d && (opt->flags&AV_OPT_FLAG_DECODING_PARAM))
+ if(!isnan(d) && (opt->flags&AV_OPT_FLAG_DECODING_PARAM))
av_set_double(ic, opt_names[i], d);
}
/* open the input file with generic libav function */
for(j=0; j<opt_name_count; j++){
const AVOption *opt;
double d= av_get_double(avctx_opts[CODEC_TYPE_AUDIO], opt_names[j], &opt);
- if(d==d && (opt->flags&AV_OPT_FLAG_AUDIO_PARAM) && (opt->flags&AV_OPT_FLAG_DECODING_PARAM))
+ if(!isnan(d) && (opt->flags&AV_OPT_FLAG_AUDIO_PARAM) && (opt->flags&AV_OPT_FLAG_DECODING_PARAM))
av_set_double(enc, opt_names[j], d);
}
//fprintf(stderr, "\nInput Audio channels: %d", enc->channels);
for(j=0; j<opt_name_count; j++){
const AVOption *opt;
double d= av_get_double(avctx_opts[CODEC_TYPE_VIDEO], opt_names[j], &opt);
- if(d==d && (opt->flags&AV_OPT_FLAG_VIDEO_PARAM) && (opt->flags&AV_OPT_FLAG_DECODING_PARAM))
+ if(!isnan(d) && (opt->flags&AV_OPT_FLAG_VIDEO_PARAM) && (opt->flags&AV_OPT_FLAG_DECODING_PARAM))
av_set_double(enc, opt_names[j], d);
}
frame_height = enc->height;
case CODEC_TYPE_DATA:
break;
case CODEC_TYPE_SUBTITLE:
+ if(subtitle_disable)
+ ic->streams[i]->discard = AVDISCARD_ALL;
break;
case CODEC_TYPE_UNKNOWN:
break;
rate_emu = 0;
}
-static void check_audio_video_inputs(int *has_video_ptr, int *has_audio_ptr)
+static void check_audio_video_sub_inputs(int *has_video_ptr, int *has_audio_ptr,
+ int *has_subtitle_ptr)
{
- int has_video, has_audio, i, j;
+ int has_video, has_audio, has_subtitle, i, j;
AVFormatContext *ic;
has_video = 0;
has_audio = 0;
+ has_subtitle = 0;
for(j=0;j<nb_input_files;j++) {
ic = input_files[j];
for(i=0;i<ic->nb_streams;i++) {
case CODEC_TYPE_VIDEO:
has_video = 1;
break;
+ case CODEC_TYPE_SUBTITLE:
+ has_subtitle = 1;
+ break;
case CODEC_TYPE_DATA:
case CODEC_TYPE_UNKNOWN:
- case CODEC_TYPE_SUBTITLE:
break;
default:
abort();
}
*has_video_ptr = has_video;
*has_audio_ptr = has_audio;
+ *has_subtitle_ptr = has_subtitle;
}
static void new_video_stream(AVFormatContext *oc)
AVCodec *codec;
codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, CODEC_TYPE_VIDEO);
- if (video_codec_id != CODEC_ID_NONE)
- codec_id = video_codec_id;
+ if (video_codec_name)
+ codec_id = find_codec_or_die(video_codec_name, CODEC_TYPE_VIDEO, 1);
video_enc->codec_id = codec_id;
codec = avcodec_find_encoder(codec_id);
for(i=0; i<opt_name_count; i++){
const AVOption *opt;
double d= av_get_double(avctx_opts[CODEC_TYPE_VIDEO], opt_names[i], &opt);
- if(d==d && (opt->flags&AV_OPT_FLAG_VIDEO_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
+ if(!isnan(d) && (opt->flags&AV_OPT_FLAG_VIDEO_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
av_set_double(video_enc, opt_names[i], d);
}
if (do_psnr)
video_enc->flags|= CODEC_FLAG_PSNR;
- video_enc->me_method = me_method;
-
/* two pass mode */
if (do_pass) {
if (do_pass == 1) {
/* reset some key parameters */
video_disable = 0;
- video_codec_id = CODEC_ID_NONE;
+ av_freep(&video_codec_name);
video_stream_copy = 0;
}
for(i=0; i<opt_name_count; i++){
const AVOption *opt;
double d= av_get_double(avctx_opts[CODEC_TYPE_AUDIO], opt_names[i], &opt);
- if(d==d && (opt->flags&AV_OPT_FLAG_AUDIO_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
+ if(!isnan(d) && (opt->flags&AV_OPT_FLAG_AUDIO_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
av_set_double(audio_enc, opt_names[i], d);
}
- if (audio_codec_id != CODEC_ID_NONE)
- codec_id = audio_codec_id;
+ if (audio_codec_name)
+ codec_id = find_codec_or_die(audio_codec_name, CODEC_TYPE_AUDIO, 1);
audio_enc->codec_id = codec_id;
if (audio_qscale > QSCALE_NONE) {
/* reset some key parameters */
audio_disable = 0;
- audio_codec_id = CODEC_ID_NONE;
+ av_freep(&audio_codec_name);
audio_stream_copy = 0;
}
-static void opt_new_subtitle_stream(void)
+static void new_subtitle_stream(AVFormatContext *oc)
{
- AVFormatContext *oc;
AVStream *st;
AVCodecContext *subtitle_enc;
int i;
- if (nb_output_files <= 0) {
- fprintf(stderr, "At least one output file must be specified\n");
- exit(1);
- }
- oc = output_files[nb_output_files - 1];
-
st = av_new_stream(oc, oc->nb_streams);
if (!st) {
fprintf(stderr, "Could not alloc stream\n");
for(i=0; i<opt_name_count; i++){
const AVOption *opt;
double d= av_get_double(avctx_opts[CODEC_TYPE_SUBTITLE], opt_names[i], &opt);
- if(d==d && (opt->flags&AV_OPT_FLAG_SUBTITLE_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
+ if(!isnan(d) && (opt->flags&AV_OPT_FLAG_SUBTITLE_PARAM) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
av_set_double(subtitle_enc, opt_names[i], d);
}
- subtitle_enc->codec_id = subtitle_codec_id;
+ subtitle_enc->codec_id = find_codec_or_die(subtitle_codec_name, CODEC_TYPE_SUBTITLE, 1);
}
if (subtitle_language) {
subtitle_language = NULL;
}
- subtitle_codec_id = CODEC_ID_NONE;
+ subtitle_disable = 0;
+ av_freep(&subtitle_codec_name);
subtitle_stream_copy = 0;
}
new_video_stream(oc);
}
+static void opt_new_subtitle_stream(void)
+{
+ AVFormatContext *oc;
+ if (nb_output_files <= 0) {
+ fprintf(stderr, "At least one output file must be specified\n");
+ exit(1);
+ }
+ oc = output_files[nb_output_files - 1];
+ new_subtitle_stream(oc);
+}
+
static void opt_output_file(const char *filename)
{
AVFormatContext *oc;
- int use_video, use_audio, input_has_video, input_has_audio, i;
+ int use_video, use_audio, use_subtitle;
+ int input_has_video, input_has_audio, input_has_subtitle, i;
AVFormatParameters params, *ap = ¶ms;
if (!strcmp(filename, "-"))
if (!file_oformat) {
file_oformat = guess_format(NULL, filename, NULL);
if (!file_oformat) {
- fprintf(stderr, "Unable for find a suitable output format for '%s'\n",
+ fprintf(stderr, "Unable to find a suitable output format for '%s'\n",
filename);
exit(1);
}
exit(1);
}
} else {
- use_video = file_oformat->video_codec != CODEC_ID_NONE || video_stream_copy || video_codec_id != CODEC_ID_NONE;
- use_audio = file_oformat->audio_codec != CODEC_ID_NONE || audio_stream_copy || audio_codec_id != CODEC_ID_NONE;
+ use_video = file_oformat->video_codec != CODEC_ID_NONE || video_stream_copy || video_codec_name;
+ use_audio = file_oformat->audio_codec != CODEC_ID_NONE || audio_stream_copy || audio_codec_name;
+ use_subtitle = file_oformat->subtitle_codec != CODEC_ID_NONE || subtitle_stream_copy || subtitle_codec_name;
/* disable if no corresponding type found and at least one
input file */
if (nb_input_files > 0) {
- check_audio_video_inputs(&input_has_video, &input_has_audio);
+ check_audio_video_sub_inputs(&input_has_video, &input_has_audio,
+ &input_has_subtitle);
if (!input_has_video)
use_video = 0;
if (!input_has_audio)
use_audio = 0;
+ if (!input_has_subtitle)
+ use_subtitle = 0;
}
/* manual disable */
if (video_disable) {
use_video = 0;
}
+ if (subtitle_disable) {
+ use_subtitle = 0;
+ }
if (use_video) {
new_video_stream(oc);
new_audio_stream(oc);
}
+ if (use_subtitle) {
+ new_subtitle_stream(oc);
+ }
+
oc->timestamp = rec_timestamp;
if (str_title)
for(i=0; i<opt_name_count; i++){
const AVOption *opt;
double d = av_get_double(avformat_opts, opt_names[i], &opt);
- if(d==d && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
+ if(!isnan(d) && (opt->flags&AV_OPT_FLAG_ENCODING_PARAM))
av_set_double(oc, opt_names[i], d);
}
do_pass = pass;
}
-#if defined(__MINGW32__) || defined(CONFIG_OS2)
-static int64_t getutime(void)
-{
- return av_gettime();
-}
-#else
static int64_t getutime(void)
{
+#ifdef HAVE_GETRUSAGE
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
-}
+#elif defined(HAVE_GETPROCESSTIMES)
+ 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
+ return av_gettime();
#endif
+}
#if defined(CONFIG_FFM_DEMUXER) || defined(CONFIG_FFM_MUXER)
extern int ffm_nopts;
#endif
-static void show_formats(void)
+static void opt_show_formats(void)
{
AVInputFormat *ifmt;
AVOutputFormat *ofmt;
URLProtocol *up;
AVCodec *p, *p2;
- const char **pp, *last_name;
+ const char *last_name;
printf("File formats:\n");
last_name= "000";
printf("\n");
printf("Frame size, frame rate abbreviations:\n ntsc pal qntsc qpal sntsc spal film ntsc-film sqcif qcif cif 4cif\n");
- printf("Motion estimation methods:\n");
- pp = motion_str;
- while (*pp) {
- printf(" %s", *pp);
- if ((pp - motion_str + 1) == ME_ZERO)
- printf("(fastest)");
- else if ((pp - motion_str + 1) == ME_FULL)
- printf("(slowest)");
- else if ((pp - motion_str + 1) == ME_EPZS)
- printf("(default)");
- pp++;
- }
- printf("\n\n");
+ printf("\n");
printf(
"Note, the names of encoders and decoders do not always match, so there are\n"
"several cases where the above table shows encoder only or decoder only entries\n"
"even though both encoding and decoding are supported. For example, the h263\n"
"decoder corresponds to the h263 and h263p encoders, for file formats it is even\n"
"worse.\n");
- exit(1);
+ exit(0);
}
static void parse_matrix_coeffs(uint16_t *dest, const char *str)
parse_matrix_coeffs(intra_matrix, arg);
}
+static void opt_show_help(void)
+{
+ show_help();
+ exit(0);
+}
+
static void opt_target(const char *arg)
{
int norm = -1;
*bsfp= bsfc;
}
-static void show_version(void)
+static void opt_show_version(void)
{
/* TODO: add function interface to avutil and avformat */
fprintf(stderr, "ffmpeg " FFMPEG_VERSION "\n"
"libavcodec %d\n"
"libavformat %d\n",
LIBAVUTIL_BUILD, avcodec_build(), LIBAVFORMAT_BUILD);
- exit(1);
+ exit(0);
}
static int opt_default(const char *opt, const char *arg){
const OptionDef options[] = {
/* main options */
- { "L", 0, {(void*)show_license}, "show license" },
- { "h", 0, {(void*)show_help}, "show help" },
- { "version", 0, {(void*)show_version}, "show version" },
- { "formats", 0, {(void*)show_formats}, "show available formats, codecs, protocols, ..." },
+ { "L", 0, {(void*)opt_show_license}, "show license" },
+ { "h", 0, {(void*)opt_show_help}, "show help" },
+ { "version", 0, {(void*)opt_show_version}, "show version" },
+ { "formats", 0, {(void*)opt_show_formats}, "show available formats, codecs, protocols, ..." },
{ "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },
{ "i", HAS_ARG, {(void*)opt_input_file}, "input file name", "filename" },
{ "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
{ "map", HAS_ARG | OPT_EXPERT, {(void*)opt_map}, "set input stream mapping", "file:stream[:syncfile:syncstream]" },
{ "map_meta_data", HAS_ARG | OPT_EXPERT, {(void*)opt_map_meta_data}, "set meta data information of outfile from infile", "outfile:infile" },
- { "t", HAS_ARG, {(void*)opt_recording_time}, "set the recording time", "duration" },
+ { "t", HAS_ARG, {(void*)opt_recording_time}, "record or transcode \"duration\" seconds of audio/video", "duration" },
{ "fs", HAS_ARG | OPT_INT64, {(void*)&limit_filesize}, "set the limit file size in bytes", "limit_size" }, //
{ "ss", HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" },
{ "itsoffset", HAS_ARG, {(void*)opt_input_ts_offset}, "set the input ts offset", "time_off" },
{ "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
{ "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" },
{ "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" },
+ { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "" },
{ "vglobal", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_global_header}, "video global header storage type", "" },
{ "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_ts}, "copy timestamps" },
{ "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest}, "finish encoding within shortest input" }, //
- { "dts_delta_threshold", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&dts_delta_threshold}, "timestamp discontinuity delta threshold", "" },
+ { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_delta_threshold}, "timestamp discontinuity delta threshold", "" },
/* video options */
{ "vframes", OPT_INT | HAS_ARG | OPT_VIDEO, {(void*)&max_frames[CODEC_TYPE_VIDEO]}, "set the number of video frames to record", "number" },
{ "rc_eq", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_rc_eq}, "set rate control equation", "equation" },
{ "rc_override", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_rc_override_string}, "rate control override for specific intervals", "override" },
{ "vcodec", HAS_ARG | OPT_VIDEO, {(void*)opt_video_codec}, "force video codec ('copy' to copy stream)", "codec" },
- { "me", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_motion_estimation}, "set motion estimation method",
- "method" },
{ "me_threshold", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_me_threshold}, "motion estimaton threshold", "" },
{ "strict", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_strict}, "how strictly to follow the standards", "strictness" },
{ "sameq", OPT_BOOL | OPT_VIDEO, {(void*)&same_quality},
{ "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" },
{ "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" },
+#ifdef CONFIG_VHOOK
{ "vhook", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)add_frame_hooker}, "insert video processing module", "module" },
+#endif
{ "intra_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_intra_matrix}, "specify intra matrix coeffs", "matrix" },
{ "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_inter_matrix}, "specify inter matrix coeffs", "matrix" },
{ "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_top_field_first}, "top=1/bottom=0/auto=-1 field first", "" },
{ "alang", HAS_ARG | OPT_STRING | OPT_AUDIO, {(void *)&audio_language}, "set the ISO 639 language code (3 letters) of the current audio stream" , "code" },
/* subtitle options */
+ { "sn", OPT_BOOL | OPT_SUBTITLE, {(void*)&subtitle_disable}, "disable subtitle" },
{ "scodec", HAS_ARG | OPT_SUBTITLE, {(void*)opt_subtitle_codec}, "force subtitle codec ('copy' to copy stream)", "codec" },
{ "newsubtitle", OPT_SUBTITLE, {(void*)opt_new_subtitle_stream}, "add a new subtitle stream to the current output stream" },
{ "slang", HAS_ARG | OPT_STRING | OPT_SUBTITLE, {(void *)&subtitle_language}, "set the ISO 639 language code (3 letters) of the current subtitle stream" , "code" },
#endif
}
-static void show_license(void)
+static void opt_show_license(void)
{
- show_banner();
-#ifdef CONFIG_GPL
- printf(
- "FFmpeg is free software; you can redistribute it and/or modify\n"
- "it under the terms of the GNU General Public License as published by\n"
- "the Free Software Foundation; either version 2 of the License, or\n"
- "(at your option) any later version.\n"
- "\n"
- "FFmpeg is distributed in the hope that it will be useful,\n"
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
- "GNU General Public License for more details.\n"
- "\n"
- "You should have received a copy of the GNU General Public License\n"
- "along with FFmpeg; if not, write to the Free Software\n"
- "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n"
- );
-#else
- printf(
- "FFmpeg is free software; you can redistribute it and/or\n"
- "modify it under the terms of the GNU Lesser General Public\n"
- "License as published by the Free Software Foundation; either\n"
- "version 2.1 of the License, or (at your option) any later version.\n"
- "\n"
- "FFmpeg is distributed in the hope that it will be useful,\n"
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
- "Lesser General Public License for more details.\n"
- "\n"
- "You should have received a copy of the GNU Lesser General Public\n"
- "License along with FFmpeg; if not, write to the Free Software\n"
- "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n"
- );
-#endif
- exit(1);
+ show_license();
+ exit(0);
}
/**
static void show_help(void)
{
av_log_set_callback(log_callback_help);
- show_banner();
printf("usage: ffmpeg [[infile options] -i infile]... {[outfile options] outfile}...\n"
"Hyper fast Audio and Video encoder\n");
printf("\n");
av_opt_show(avctx_opts[0], NULL);
av_opt_show(avformat_opts, NULL);
av_opt_show(sws_opts, NULL);
-
- exit(1);
-}
-
-void parse_arg_file(const char *filename)
-{
- opt_output_file(filename);
}
int main(int argc, char **argv)
avformat_opts = av_alloc_format_context();
sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
- if (argc <= 1)
+ show_banner();
+ if (argc <= 1) {
show_help();
- else
- show_banner();
+ exit(1);
+ }
/* parse options */
- parse_options(argc, argv, options);
+ parse_options(argc, argv, options, opt_output_file);
/* file converter / grab */
if (nb_output_files <= 0) {
av_free(intra_matrix);
av_free(inter_matrix);
- if (fvstats)
- fclose(fvstats);
+ if (vstats_file)
+ fclose(vstats_file);
av_free(vstats_filename);
av_free(opt_names);
+ av_free(video_codec_name);
+ av_free(audio_codec_name);
+ av_free(subtitle_codec_name);
+
av_free(video_standard);
#ifdef CONFIG_POWERPC_PERF