diff options
Diffstat (limited to 'ffmpeg.c')
-rw-r--r-- | ffmpeg.c | 439 |
1 files changed, 286 insertions, 153 deletions
@@ -2,20 +2,20 @@ * ffmpeg main * Copyright (c) 2000-2003 Fabrice Bellard * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -47,6 +47,8 @@ #include "libavutil/libm.h" #include "libavformat/os_support.h" +#include "libavformat/ffm.h" // not public API + #if CONFIG_AVFILTER # include "libavfilter/avfilter.h" # include "libavfilter/avfiltergraph.h" @@ -69,7 +71,12 @@ #include <sys/select.h> #endif -#if HAVE_KBHIT +#if HAVE_TERMIOS_H +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <termios.h> +#elif HAVE_KBHIT #include <conio.h> #endif #include <time.h> @@ -108,8 +115,6 @@ static const OptionDef options[]; #define MAX_FILES 100 #define MAX_STREAMS 1024 /* arbitrary sanity check value */ -#define FFM_PACKET_SIZE 4096 //XXX a duplicate of the line in ffm.h - static const char *last_asked_format = NULL; static AVFormatContext *input_files[MAX_FILES]; static int64_t input_files_ts_offset[MAX_FILES]; @@ -145,6 +150,7 @@ static int frame_width = 0; static int frame_height = 0; static float frame_aspect_ratio = 0; static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE; +static int frame_bits_per_raw_sample = 0; static enum AVSampleFormat audio_sample_fmt = AV_SAMPLE_FMT_NONE; static int max_frames[4] = {INT_MAX, INT_MAX, INT_MAX, INT_MAX}; static AVRational frame_rate; @@ -167,7 +173,8 @@ static int loop_output = AVFMT_NOOUTPUTLOOP; static int qp_hist = 0; #if CONFIG_AVFILTER static char *vfilters = NULL; -static AVFilterGraph *graph = NULL; +#else +static unsigned int sws_flags = SWS_BICUBIC; #endif static int intra_only = 0; @@ -200,7 +207,7 @@ static int do_hex_dump = 0; static int do_pkt_dump = 0; static int do_psnr = 0; static int do_pass = 0; -static char *pass_logfilename_prefix = NULL; +static const char *pass_logfilename_prefix; static int audio_stream_copy = 0; static int video_stream_copy = 0; static int subtitle_stream_copy = 0; @@ -226,6 +233,7 @@ static int audio_volume = 256; static int exit_on_error = 0; static int using_stdin = 0; static int verbose = 1; +static int run_as_daemon = 0; static int thread_count= 1; static int q_pressed = 0; static int64_t video_size = 0; @@ -240,8 +248,6 @@ static char *forced_key_frames = NULL; static float dts_delta_threshold = 10; -static unsigned int sws_flags = SWS_BICUBIC; - static int64_t timer_start; static uint8_t *audio_buf; @@ -279,9 +285,7 @@ typedef struct AVOutputStream { int resample_width; int resample_pix_fmt; - /* full frame size of first frame */ - int original_height; - int original_width; + float frame_aspect_ratio; /* forced key frames */ int64_t *forced_kf_pts; @@ -298,6 +302,14 @@ typedef struct AVOutputStream { AVAudioConvert *reformat_ctx; AVFifoBuffer *fifo; /* for compression: one audio fifo per codec */ FILE *logfile; + +#if CONFIG_AVFILTER + AVFilterContext *output_video_filter; + AVFilterContext *input_video_filter; + AVFilterBufferRef *picref; + char *avfilter; + AVFilterGraph *graph; +#endif } AVOutputStream; static AVOutputStream **output_streams_for_file[MAX_FILES] = { NULL }; @@ -315,16 +327,12 @@ typedef struct AVInputStream { int64_t next_pts; /* synthetic pts for cases where pkt.pts is not defined */ int64_t pts; /* current pts */ - PtsCorrectionContext pts_ctx; int is_start; /* is 1 at the start and after a discontinuity */ int showed_multi_packet_warning; int is_past_recording_time; #if CONFIG_AVFILTER - AVFilterContext *output_video_filter; - AVFilterContext *input_video_filter; AVFrame *filter_frame; int has_filter_frame; - AVFilterBufferRef *picref; #endif } AVInputStream; @@ -335,9 +343,15 @@ typedef struct AVInputFile { int nb_streams; /* nb streams we are aware of */ } AVInputFile; +#if HAVE_TERMIOS_H + +/* init terminal so that we can grab keys */ +static struct termios oldtty; +#endif + #if CONFIG_AVFILTER -static int configure_filters(AVInputStream *ist, AVOutputStream *ost) +static int configure_video_filters(AVInputStream *ist, AVOutputStream *ost) { AVFilterContext *last_filter, *filter; /** filter graph containing all filters including input & output */ @@ -348,7 +362,7 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost) char args[255]; int ret; - graph = avfilter_graph_alloc(); + ost->graph = avfilter_graph_alloc(); if (ist->st->sample_aspect_ratio.num){ sample_aspect_ratio = ist->st->sample_aspect_ratio; @@ -359,15 +373,15 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost) ist->st->codec->height, ist->st->codec->pix_fmt, 1, AV_TIME_BASE, sample_aspect_ratio.num, sample_aspect_ratio.den); - ret = avfilter_graph_create_filter(&ist->input_video_filter, avfilter_get_by_name("buffer"), - "src", args, NULL, graph); + ret = avfilter_graph_create_filter(&ost->input_video_filter, avfilter_get_by_name("buffer"), + "src", args, NULL, ost->graph); if (ret < 0) return ret; - ret = avfilter_graph_create_filter(&ist->output_video_filter, &ffsink, - "out", NULL, &ffsink_ctx, graph); + ret = avfilter_graph_create_filter(&ost->output_video_filter, &ffsink, + "out", NULL, &ffsink_ctx, ost->graph); if (ret < 0) return ret; - last_filter = ist->input_video_filter; + last_filter = ost->input_video_filter; if (codec->width != icodec->width || codec->height != icodec->height) { snprintf(args, 255, "%d:%d:flags=0x%X", @@ -375,7 +389,7 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost) codec->height, (int)av_get_int(sws_opts, "sws_flags", NULL)); if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"), - NULL, args, NULL, graph)) < 0) + NULL, args, NULL, ost->graph)) < 0) return ret; if ((ret = avfilter_link(last_filter, 0, filter, 0)) < 0) return ret; @@ -383,9 +397,9 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost) } snprintf(args, sizeof(args), "flags=0x%X", (int)av_get_int(sws_opts, "sws_flags", NULL)); - graph->scale_sws_opts = av_strdup(args); + ost->graph->scale_sws_opts = av_strdup(args); - if (vfilters) { + if (ost->avfilter) { AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut)); AVFilterInOut *inputs = av_malloc(sizeof(AVFilterInOut)); @@ -395,25 +409,27 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost) outputs->next = NULL; inputs->name = av_strdup("out"); - inputs->filter_ctx = ist->output_video_filter; + inputs->filter_ctx = ost->output_video_filter; inputs->pad_idx = 0; inputs->next = NULL; - if ((ret = avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL)) < 0) + if ((ret = avfilter_graph_parse(ost->graph, ost->avfilter, inputs, outputs, NULL)) < 0) return ret; - av_freep(&vfilters); + av_freep(&ost->avfilter); } else { - if ((ret = avfilter_link(last_filter, 0, ist->output_video_filter, 0)) < 0) + if ((ret = avfilter_link(last_filter, 0, ost->output_video_filter, 0)) < 0) return ret; } - if ((ret = avfilter_graph_config(graph, NULL)) < 0) + if ((ret = avfilter_graph_config(ost->graph, NULL)) < 0) return ret; - codec->width = ist->output_video_filter->inputs[0]->w; - codec->height = ist->output_video_filter->inputs[0]->h; + codec->width = ost->output_video_filter->inputs[0]->w; + codec->height = ost->output_video_filter->inputs[0]->h; codec->sample_aspect_ratio = ost->st->sample_aspect_ratio = - ist->output_video_filter->inputs[0]->sample_aspect_ratio; + ost->frame_aspect_ratio ? // overriden by the -aspect cli option + av_d2q(ost->frame_aspect_ratio*codec->height/codec->width, 255) : + ost->output_video_filter->inputs[0]->sample_aspect_ratio; return 0; } @@ -422,6 +438,10 @@ static int configure_filters(AVInputStream *ist, AVOutputStream *ost) static void term_exit(void) { av_log(NULL, AV_LOG_QUIET, ""); +#if HAVE_TERMIOS_H + if(!run_as_daemon) + tcsetattr (0, TCSANOW, &oldtty); +#endif } static volatile int received_sigterm = 0; @@ -430,11 +450,34 @@ static void sigterm_handler(int sig) { received_sigterm = sig; + q_pressed++; term_exit(); } static void term_init(void) { +#if HAVE_TERMIOS_H + if(!run_as_daemon){ + 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). */ + } +#endif + signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */ signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */ #ifdef SIGXCPU @@ -445,7 +488,28 @@ static void term_init(void) /* read a key without blocking */ static int read_key(void) { -#if HAVE_KBHIT +#if HAVE_TERMIOS_H + int n = 1; + unsigned char ch; + struct timeval tv; + fd_set rfds; + + if(run_as_daemon) + return -1; + + 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 if(kbhit()) return(getch()); #endif @@ -454,7 +518,8 @@ static int read_key(void) static int decode_interrupt_cb(void) { - return q_pressed || (q_pressed = read_key() == 'q'); + q_pressed += read_key() == 'q'; + return q_pressed > 1; } static int ffmpeg_exit(int ret) @@ -588,8 +653,15 @@ static void choose_pixel_fmt(AVStream *st, AVCodec *codec) if(*p == st->codec->pix_fmt) break; } - if(*p == -1) + if (*p == -1) { + if(st->codec->pix_fmt != PIX_FMT_NONE) + av_log(NULL, AV_LOG_WARNING, + "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[codec->pix_fmts[0]].name); st->codec->pix_fmt = codec->pix_fmts[0]; + } } } @@ -1067,8 +1139,8 @@ static void do_video_out(AVFormatContext *s, AVFrame *in_picture, int *frame_size) { - int nb_frames, i, ret; - AVFrame *final_picture, *formatted_picture, *resampling_dst, *padding_src; + int nb_frames, i, ret, resample_changed; + AVFrame *final_picture, *formatted_picture, *resampling_dst; AVCodecContext *enc, *dec; double sync_ipts; @@ -1113,26 +1185,26 @@ static void do_video_out(AVFormatContext *s, formatted_picture = in_picture; final_picture = formatted_picture; - padding_src = formatted_picture; resampling_dst = &ost->pict_tmp; - if ( ost->resample_height != ist->st->codec->height - || ost->resample_width != ist->st->codec->width - || (ost->resample_pix_fmt!= ist->st->codec->pix_fmt) ) { + resample_changed = ost->resample_width != dec->width || + ost->resample_height != dec->height || + ost->resample_pix_fmt != dec->pix_fmt; - fprintf(stderr,"Input Stream #%d.%d frame size changed to %dx%d, %s\n", ist->file_index, ist->index, ist->st->codec->width, ist->st->codec->height,avcodec_get_pix_fmt_name(ist->st->codec->pix_fmt)); + if (resample_changed) { + av_log(NULL, AV_LOG_INFO, + "Input stream #%d.%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", + ist->file_index, ist->index, + ost->resample_width, ost->resample_height, avcodec_get_pix_fmt_name(ost->resample_pix_fmt), + dec->width , dec->height , avcodec_get_pix_fmt_name(dec->pix_fmt)); if(!ost->video_resample) ffmpeg_exit(1); } #if !CONFIG_AVFILTER if (ost->video_resample) { - padding_src = NULL; final_picture = &ost->pict_tmp; - if( ost->resample_height != ist->st->codec->height - || ost->resample_width != ist->st->codec->width - || (ost->resample_pix_fmt!= ist->st->codec->pix_fmt) ) { - + if (resample_changed) { /* initialize a new scaler context */ sws_freeContext(ost->img_resample_ctx); sws_flags = av_get_int(sws_opts, "sws_flags", NULL); @@ -1315,26 +1387,25 @@ static void print_report(AVFormatContext **output_files, ti1 = 1e10; vid = 0; for(i=0;i<nb_ostreams;i++) { + float q= -1; ost = ost_table[i]; enc = ost->st->codec; + if(!ost->st->stream_copy && enc->coded_frame) + q= enc->coded_frame->quality/(float)FF_QP2LAMBDA; if (vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", - !ost->st->stream_copy ? - enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", q); } if (!vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) { float t = (av_gettime()-timer_start) / 1000000.0; frame_number = ost->frame_number; snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3d q=%3.1f ", - frame_number, (t>1)?(int)(frame_number/t+0.5) : 0, - !ost->st->stream_copy ? - enc->coded_frame->quality/(float)FF_QP2LAMBDA : -1); + frame_number, (t>1)?(int)(frame_number/t+0.5) : 0, q); if(is_last_report) snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L"); if(qp_hist){ int j; - int qp= lrintf(enc->coded_frame->quality/(float)FF_QP2LAMBDA); + int qp= lrintf(q); if(qp>=0 && qp<FF_ARRAY_ELEMS(qp_histogram)) qp_histogram[qp]++; for(j=0; j<32; j++) @@ -1371,7 +1442,7 @@ static void print_report(AVFormatContext **output_files, if (ti1 < 0.01) ti1 = 0.01; - if (verbose || is_last_report) { + if (verbose > 0 || is_last_report) { bitrate = (double)(total_size * 8) / ti1 / 1000.0; snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), @@ -1418,7 +1489,7 @@ static int output_packet(AVInputStream *ist, int ist_index, int ret, i; int got_picture; AVFrame picture; - void *buffer_to_free; + void *buffer_to_free = NULL; static unsigned int samples_size= 0; AVSubtitle subtitle, *subtitle_to_free; int64_t pkt_pts = AV_NOPTS_VALUE; @@ -1511,7 +1582,7 @@ static int output_packet(AVInputStream *ist, int ist_index, /* no picture yet */ goto discard_packet; } - ist->next_pts = ist->pts = guess_correct_pts(&ist->pts_ctx, picture.pkt_pts, picture.pkt_dts); + ist->next_pts = ist->pts = picture.best_effort_timestamp; if (ist->st->codec->time_base.num != 0) { int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame; ist->next_pts += ((int64_t)AV_TIME_BASE * @@ -1519,6 +1590,8 @@ static int output_packet(AVInputStream *ist, int ist_index, ist->st->codec->time_base.den; } avpkt.size = 0; + buffer_to_free = NULL; + pre_process_video_frame(ist, (AVPicture *)&picture, &buffer_to_free); break; case AVMEDIA_TYPE_SUBTITLE: ret = avcodec_decode_subtitle2(ist->st->codec, @@ -1553,21 +1626,21 @@ static int output_packet(AVInputStream *ist, int ist_index, avpkt.size = 0; } - buffer_to_free = NULL; - if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - pre_process_video_frame(ist, (AVPicture *)&picture, - &buffer_to_free); - } - #if CONFIG_AVFILTER - if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ist->input_video_filter) { - AVRational sar; - if (ist->st->sample_aspect_ratio.num) sar = ist->st->sample_aspect_ratio; - else sar = ist->st->codec->sample_aspect_ratio; - // add it to be filtered - av_vsrc_buffer_add_frame(ist->input_video_filter, &picture, - ist->pts, - sar); + if(ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO){ + for(i=0;i<nb_ostreams;i++) { + ost = ost_table[i]; + if (ost->input_video_filter && ost->source_index == ist_index) { + AVRational sar; + if (ist->st->sample_aspect_ratio.num) sar = ist->st->sample_aspect_ratio; + else sar = ist->st->codec->sample_aspect_ratio; + // add it to be filtered + av_vsrc_buffer_add_frame2(ost->input_video_filter, &picture, + ist->pts, + sar, ist->st->codec->width, ist->st->codec->height, + ist->st->codec->pix_fmt, ""); //TODO user setable params + } + } } #endif @@ -1592,26 +1665,24 @@ static int output_packet(AVInputStream *ist, int ist_index, if (pts > now) usleep(pts - now); } -#if CONFIG_AVFILTER - frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || - !ist->output_video_filter || avfilter_poll_frame(ist->output_video_filter->inputs[0]); -#endif /* if output time reached then transcode raw format, encode packets and output them */ if (start_time == 0 || ist->pts >= start_time) -#if CONFIG_AVFILTER - while (frame_available) { - AVRational ist_pts_tb; - if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ist->output_video_filter) - get_filtered_video_frame(ist->output_video_filter, &picture, &ist->picref, &ist_pts_tb); - if (ist->picref) - ist->pts = av_rescale_q(ist->picref->pts, ist_pts_tb, AV_TIME_BASE_Q); -#endif for(i=0;i<nb_ostreams;i++) { int frame_size; ost = ost_table[i]; if (ost->source_index == ist_index) { +#if CONFIG_AVFILTER + frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || + !ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]); + while (frame_available) { + AVRational ist_pts_tb; + if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->output_video_filter) + get_filtered_video_frame(ost->output_video_filter, &picture, &ost->picref, &ist_pts_tb); + if (ost->picref) + ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q); +#endif os = output_files[ost->file_index]; /* set the input output pts pairs */ @@ -1625,8 +1696,8 @@ static int output_packet(AVInputStream *ist, int ist_index, break; case AVMEDIA_TYPE_VIDEO: #if CONFIG_AVFILTER - if (ist->picref->video) - ost->st->codec->sample_aspect_ratio = ist->picref->video->pixel_aspect; + if (ost->picref->video && !ost->frame_aspect_ratio) + ost->st->codec->sample_aspect_ratio = ost->picref->video->pixel_aspect; #endif do_video_out(os, ost, ist, &picture, &frame_size); if (vstats_filename && frame_size) @@ -1647,7 +1718,11 @@ static int output_packet(AVInputStream *ist, int ist_index, av_init_packet(&opkt); if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !copy_initial_nonkeyframes) +#if !CONFIG_AVFILTER continue; +#else + goto cont; +#endif /* no reencoding needed : output the packet directly */ /* force the input stream PTS */ @@ -1695,16 +1770,17 @@ static int output_packet(AVInputStream *ist, int ist_index, ost->frame_number++; av_free_packet(&opkt); } +#if CONFIG_AVFILTER + cont: + frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && + ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]); + if(ost->picref) + avfilter_unref_buffer(ost->picref); + } +#endif } } -#if CONFIG_AVFILTER - frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && - ist->output_video_filter && avfilter_poll_frame(ist->output_video_filter->inputs[0]); - if(ist->picref) - avfilter_unref_buffer(ist->picref); - } -#endif av_free(buffer_to_free); /* XXX: allocate the subtitles in the codec ? */ if (subtitle_to_free) { @@ -1884,7 +1960,7 @@ static int transcode(AVFormatContext **output_files, int nb_input_files, AVStreamMap *stream_maps, int nb_stream_maps) { - int ret = 0, i, j, k, n, nb_istreams = 0, nb_ostreams = 0; + int ret = 0, i, j, k, n, nb_istreams = 0, nb_ostreams = 0, step; AVFormatContext *is, *os; AVCodecContext *codec, *icodec; AVOutputStream *ost, **ost_table = NULL; @@ -1895,6 +1971,8 @@ static int transcode(AVFormatContext **output_files, int want_sdp = 1; uint8_t no_packet[MAX_FILES]={0}; int no_packet_count=0; + int nb_frame_threshold[AVMEDIA_TYPE_NB]={0}; + int nb_streams[AVMEDIA_TYPE_NB]={0}; file_table= av_mallocz(nb_input_files * sizeof(AVInputFile)); if (!file_table) @@ -1979,6 +2057,43 @@ static int transcode(AVFormatContext **output_files, ost_table = av_mallocz(sizeof(AVOutputStream *) * nb_ostreams); if (!ost_table) goto fail; + + for(k=0;k<nb_output_files;k++) { + os = output_files[k]; + for(i=0;i<os->nb_streams;i++,n++) { + nb_streams[os->streams[i]->codec->codec_type]++; + } + } + for(step=1<<30; step; step>>=1){ + int found_streams[AVMEDIA_TYPE_NB]={0}; + for(j=0; j<AVMEDIA_TYPE_NB; j++) + nb_frame_threshold[j] += step; + + for(j=0; j<nb_istreams; j++) { + int skip=0; + ist = ist_table[j]; + if(opt_programid){ + int pi,si; + AVFormatContext *f= input_files[ ist->file_index ]; + skip=1; + for(pi=0; pi<f->nb_programs; pi++){ + AVProgram *p= f->programs[pi]; + if(p->id == opt_programid) + for(si=0; si<p->nb_stream_indexes; si++){ + if(f->streams[ p->stream_index[si] ] == ist->st) + skip=0; + } + } + } + if (ist->discard && ist->st->discard != AVDISCARD_ALL && !skip + && nb_frame_threshold[ist->st->codec->codec_type] <= ist->st->codec_info_nb_frames){ + found_streams[ist->st->codec->codec_type]++; + } + } + for(j=0; j<AVMEDIA_TYPE_NB; j++) + if(found_streams[j] < nb_streams[j]) + nb_frame_threshold[j] -= step; + } n = 0; for(k=0;k<nb_output_files;k++) { os = output_files[k]; @@ -2001,7 +2116,6 @@ static int transcode(AVFormatContext **output_files, } } else { - int best_nb_frames=-1; /* get corresponding input stream index : we select the first one with the right type */ found = 0; for(j=0;j<nb_istreams;j++) { @@ -2021,12 +2135,11 @@ static int transcode(AVFormatContext **output_files, } } if (ist->discard && ist->st->discard != AVDISCARD_ALL && !skip && - ist->st->codec->codec_type == ost->st->codec->codec_type) { - if(best_nb_frames < ist->st->codec_info_nb_frames){ - best_nb_frames= ist->st->codec_info_nb_frames; + ist->st->codec->codec_type == ost->st->codec->codec_type && + nb_frame_threshold[ist->st->codec->codec_type] <= ist->st->codec_info_nb_frames) { ost->source_index = j; found = 1; - } + break; } } @@ -2130,6 +2243,13 @@ static int transcode(AVFormatContext **output_files, codec->width = icodec->width; codec->height = icodec->height; codec->has_b_frames = icodec->has_b_frames; + if (!codec->sample_aspect_ratio.num) { + codec->sample_aspect_ratio = + 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}; + } break; case AVMEDIA_TYPE_SUBTITLE: codec->width = icodec->width; @@ -2158,9 +2278,9 @@ static int transcode(AVFormatContext **output_files, fprintf(stderr, "Video pixel format is unknown, stream cannot be encoded\n"); ffmpeg_exit(1); } - ost->video_resample = (codec->width != icodec->width || - codec->height != icodec->height || - (codec->pix_fmt != icodec->pix_fmt)); + ost->video_resample = codec->width != icodec->width || + codec->height != icodec->height || + codec->pix_fmt != icodec->pix_fmt; if (ost->video_resample) { #if !CONFIG_AVFILTER avcodec_get_frame_defaults(&ost->pict_tmp); @@ -2182,11 +2302,8 @@ static int transcode(AVFormatContext **output_files, fprintf(stderr, "Cannot get resampling context\n"); ffmpeg_exit(1); } - - ost->original_height = icodec->height; - ost->original_width = icodec->width; #endif - codec->bits_per_raw_sample= 0; + codec->bits_per_raw_sample= frame_bits_per_raw_sample; } ost->resample_height = icodec->height; ost->resample_width = icodec->width; @@ -2195,7 +2312,7 @@ static int transcode(AVFormatContext **output_files, ist->decoding_needed = 1; #if CONFIG_AVFILTER - if (configure_filters(ist, ost)) { + if (configure_video_filters(ist, ost)) { fprintf(stderr, "Error opening filters!\n"); exit(1); } @@ -2210,7 +2327,7 @@ static int transcode(AVFormatContext **output_files, break; } /* two pass mode */ - if (ost->encoding_needed && + if (ost->encoding_needed && codec->codec_id != CODEC_ID_H264 && (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) { char logfilename[1024]; FILE *f; @@ -2237,8 +2354,9 @@ static int transcode(AVFormatContext **output_files, } } if(codec->codec_type == AVMEDIA_TYPE_VIDEO){ + /* maximum video buffer size is 6-bytes per pixel, plus DPX header size */ int size= codec->width * codec->height; - bit_buffer_size= FFMAX(bit_buffer_size, 6*size + 200); + bit_buffer_size= FFMAX(bit_buffer_size, 6*size + 1664); } } @@ -2315,7 +2433,6 @@ static int transcode(AVFormatContext **output_files, st= ist->st; ist->pts = st->avg_frame_rate.num ? - st->codec->has_b_frames*AV_TIME_BASE / av_q2d(st->avg_frame_rate) : 0; ist->next_pts = AV_NOPTS_VALUE; - init_pts_correction(&ist->pts_ctx); ist->is_start = 1; } @@ -2455,12 +2572,9 @@ static int transcode(AVFormatContext **output_files, print_sdp(output_files, nb_output_files); } - if (!using_stdin && verbose >= 0) { -#if HAVE_KBHIT - fprintf(stderr, "Press [q] to stop encoding\n"); -#else - fprintf(stderr, "Press ctrl-c to stop encoding\n"); -#endif + if (!using_stdin) { + if(verbose >= 0) + fprintf(stderr, "Press [q] to stop encoding\n"); avio_set_interrupt_cb(decode_interrupt_cb); } term_init(); @@ -2640,6 +2754,9 @@ static int transcode(AVFormatContext **output_files, av_freep(&ost->st->codec->stats_in); avcodec_close(ost->st->codec); } +#if CONFIG_AVFILTER + avfilter_graph_free(&ost->graph); +#endif } /* close each decoder */ @@ -2649,9 +2766,6 @@ static int transcode(AVFormatContext **output_files, avcodec_close(ist->st->codec); } } -#if CONFIG_AVFILTER - avfilter_graph_free(&graph); -#endif /* finished ! */ ret = 0; @@ -2815,19 +2929,20 @@ static int opt_metadata(const char *opt, const char *arg) return 0; } -static void opt_qscale(const char *arg) +static int opt_qscale(const char *opt, const char *arg) { - video_qscale = atof(arg); - if (video_qscale <= 0 || - video_qscale > 255) { + video_qscale = parse_number_or_die(opt, arg, OPT_FLOAT, 0, 255); + if (video_qscale <= 0 || video_qscale > 255) { fprintf(stderr, "qscale must be > 0.0 and <= 255\n"); - ffmpeg_exit(1); + return AVERROR(EINVAL); } + return 0; } -static void opt_top_field_first(const char *arg) +static int opt_top_field_first(const char *opt, const char *arg) { - top_field_first= atoi(arg); + top_field_first = parse_number_or_die(opt, arg, OPT_INT, 0, 1); + return 0; } static int opt_thread_count(const char *opt, const char *arg) @@ -2849,7 +2964,10 @@ static void opt_audio_sample_fmt(const char *arg) ffmpeg_exit(1); } } else { - list_fmts(av_get_sample_fmt_string, AV_SAMPLE_FMT_NB); + int i; + char fmt_str[128]; + for (i = -1; i < AV_SAMPLE_FMT_NB; i++) + printf("%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i)); ffmpeg_exit(0); } } @@ -2866,9 +2984,10 @@ static int opt_audio_channels(const char *opt, const char *arg) return 0; } -static void opt_video_channel(const char *arg) +static int opt_video_channel(const char *opt, const char *arg) { - video_channel = strtol(arg, NULL, 0); + video_channel = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX); + return 0; } static void opt_video_standard(const char *arg) @@ -3230,11 +3349,6 @@ static void opt_input_file(const char *filename) set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, input_codecs[nb_input_codecs-1]); frame_height = dec->height; frame_width = dec->width; - if(ic->streams[i]->sample_aspect_ratio.num) - frame_aspect_ratio=av_q2d(ic->streams[i]->sample_aspect_ratio); - else - frame_aspect_ratio=av_q2d(dec->sample_aspect_ratio); - frame_aspect_ratio *= (float) dec->width / dec->height; frame_pix_fmt = dec->pix_fmt; rfps = ic->streams[i]->r_frame_rate.num; rfps_base = ic->streams[i]->r_frame_rate.den; @@ -3358,6 +3472,12 @@ static void new_video_stream(AVFormatContext *oc, int file_idx) codec_id = av_guess_codec(oc->oformat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO); codec = avcodec_find_encoder(codec_id); } + ost->frame_aspect_ratio = frame_aspect_ratio; + frame_aspect_ratio = 0; +#if CONFIG_AVFILTER + ost->avfilter= vfilters; + vfilters= NULL; +#endif } avcodec_get_context_defaults3(st->codec, codec); @@ -3401,8 +3521,8 @@ static void new_video_stream(AVFormatContext *oc, int file_idx) video_enc->width = frame_width; video_enc->height = frame_height; - video_enc->sample_aspect_ratio = av_d2q(frame_aspect_ratio*video_enc->height/video_enc->width, 255); video_enc->pix_fmt = frame_pix_fmt; + video_enc->bits_per_raw_sample = frame_bits_per_raw_sample; st->sample_aspect_ratio = video_enc->sample_aspect_ratio; choose_pixel_fmt(st, codec); @@ -3780,7 +3900,6 @@ static void opt_output_file(const char *filename) oc->preload= (int)(mux_preload*AV_TIME_BASE); oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE); oc->loop_output = loop_output; - oc->flags |= AVFMT_FLAG_NONBLOCK; set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM, NULL); @@ -3788,15 +3907,10 @@ static void opt_output_file(const char *filename) } /* same option as mencoder */ -static void opt_pass(const char *pass_str) +static int opt_pass(const char *opt, const char *arg) { - int pass; - pass = atoi(pass_str); - if (pass != 1 && pass != 2) { - fprintf(stderr, "pass number can be only 1 or 2\n"); - ffmpeg_exit(1); - } - do_pass = pass; + do_pass = parse_number_or_die(opt, arg, OPT_INT, 1, 2); + return 0; } static int64_t getutime(void) @@ -3973,7 +4087,7 @@ static void opt_target(const char *arg) } } } - if(verbose && norm != UNKNOWN) + if(verbose > 0 && norm != UNKNOWN) fprintf(stderr, "Assuming %s for target.\n", norm == PAL ? "PAL" : "NTSC"); } @@ -4150,6 +4264,16 @@ static int opt_preset(const char *opt, const char *arg) return 0; } +static void log_callback_null(void* ptr, int level, const char* fmt, va_list vl) +{ +} + +static void opt_passlogfile(const char *arg) +{ + pass_logfilename_prefix = arg; + opt_default("passlogfile", arg); +} + static const OptionDef options[] = { /* main options */ #include "cmdutils_common_opts.h" @@ -4203,6 +4327,7 @@ static const OptionDef options[] = { { "s", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_size}, "set frame size (WxH or abbreviation)", "size" }, { "aspect", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_aspect_ratio}, "set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)", "aspect" }, { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_frame_pix_fmt}, "set pixel format, 'list' as argument shows all the pixel formats supported", "format" }, + { "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" }, { "croptop", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" }, { "cropbottom", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" }, { "cropleft", OPT_FUNC2 | HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" }, @@ -4215,14 +4340,14 @@ static const OptionDef options[] = { { "intra", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_only}, "use only intra frames"}, { "vn", OPT_BOOL | OPT_VIDEO, {(void*)&video_disable}, "disable video" }, { "vdt", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&video_discard}, "discard threshold", "n" }, - { "qscale", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qscale}, "use fixed video quantizer scale (VBR)", "q" }, + { "qscale", HAS_ARG | OPT_FUNC2 | OPT_EXPERT | OPT_VIDEO, {(void*)opt_qscale}, "use fixed video quantizer scale (VBR)", "q" }, { "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_threshold", HAS_ARG | OPT_FUNC2 | OPT_EXPERT | OPT_VIDEO, {(void*)opt_me_threshold}, "motion estimaton threshold", "threshold" }, { "sameq", OPT_BOOL | OPT_VIDEO, {(void*)&same_quality}, "use same quantizer as source (implies VBR)" }, - { "pass", HAS_ARG | OPT_VIDEO, {(void*)&opt_pass}, "select the pass number (1 or 2)", "n" }, - { "passlogfile", HAS_ARG | OPT_STRING | OPT_VIDEO, {(void*)&pass_logfilename_prefix}, "select two pass log file name prefix", "prefix" }, + { "pass", HAS_ARG | OPT_FUNC2 | OPT_VIDEO, {(void*)opt_pass}, "select the pass number (1 or 2)", "n" }, + { "passlogfile", HAS_ARG | OPT_VIDEO, {(void*)&opt_passlogfile}, "select two pass log file name prefix", "prefix" }, { "deinterlace", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_deinterlace}, "deinterlace pictures" }, { "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" }, @@ -4233,7 +4358,7 @@ static const OptionDef options[] = { #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", "" }, + { "top", HAS_ARG | OPT_FUNC2 | OPT_EXPERT | OPT_VIDEO, {(void*)opt_top_field_first}, "top=1/bottom=0/auto=-1 field first", "" }, { "dc", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_dc_precision}, "intra_dc_precision", "precision" }, { "vtag", OPT_FUNC2 | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_codec_tag}, "force video tag/fourcc", "fourcc/tag" }, { "newvideo", OPT_VIDEO | OPT_FUNC2, {(void*)opt_new_stream}, "add a new video stream to the current output stream" }, @@ -4265,7 +4390,7 @@ static const OptionDef options[] = { { "stag", OPT_FUNC2 | HAS_ARG | OPT_EXPERT | OPT_SUBTITLE, {(void*)opt_codec_tag}, "force subtitle tag/fourcc", "fourcc/tag" }, /* grab options */ - { "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_channel}, "set video grab channel (DV1394 only)", "channel" }, + { "vc", HAS_ARG | OPT_FUNC2 | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_channel}, "set video grab channel (DV1394 only)", "channel" }, { "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_standard}, "set television standard (NTSC, PAL (SECAM))", "standard" }, { "isync", OPT_BOOL | OPT_EXPERT | OPT_GRAB, {(void*)&input_sync}, "sync read on input", "" }, @@ -4292,6 +4417,14 @@ int main(int argc, char **argv) av_log_set_flags(AV_LOG_SKIP_REPEATED); + if(argc>1 && !strcmp(argv[1], "-d")){ + run_as_daemon=1; + verbose=-1; + av_log_set_callback(log_callback_null); + argc--; + argv++; + } + avcodec_register_all(); #if CONFIG_AVDEVICE avdevice_register_all(); |