History

Merge commit '3b266da3d35f3f7a61258b78384dfe920d875d29'

* commit '3b266da3d35f3f7a61258b78384dfe920d875d29': avconv: add support for complex filtergraphs. avconv: make filtergraphs global. avconv: move filtered_frame from InputStream to OutputStream. avconv: don't set output width/height directly from input value. avconv: move resample_{width,height,pix_fmt} to InputStream. avconv: remove a useless variable from OutputStream. avconv: get output pixel format from lavfi. graphparser: fix the order in which unlabeled input links are returned. avconv: change {input,output}_{streams,files} into arrays of pointers. avconv: don't pass input/output streams to some functions. Conflicts: cmdutils.c cmdutils.h doc/ffmpeg.texi ffmpeg.c ffplay.c

Michael Niedermayer committed 14 years ago

Commit 47787832 parents dcd207c 3b266da11 files · +924 −415Browse files

Unified · Split

11 files
  1. cmdutils.h +1 −0
  2. doc/ffmpeg.texi +46 −1
  3. doc/filters.texi +1 −0
  4. ffmpeg.c +864 −352
  5. ffplay.c +1 −1
  6. libavfilter/graphparser.c +1 −1
  7. libavfilter/sink_buffer.c +7 −3
  8. tests/codec-regression.sh +3 −3
  9. tests/ref/seek/mpeg2reuse_mpg +0 −46
  10. tests/ref/vsynth1/mpeg2thread_ilace +0 −4
  11. tests/ref/vsynth2/mpeg2thread_ilace +0 −4
cmdutils.h+1−0
@@ -370,6 +370,7 @@ int cmdutils_read_file(const char *filename, char **bufptr, size_t *size); · 369 unmodified lines
370370 FILE *get_preset_file(char *filename, size_t filename_size,
371371 const char *preset_name, int is_path, const char *codec_name);
372372
373+
373374 /**
374375 * Do all the necessary cleanup and abort.
375376 * This function is implemented in the avtools, not cmdutils.
doc/ffmpeg.texi+46−1
@@ -224,6 +224,9 @@ codec-dependent. · 223 unmodified lines
224224 @var{filter_graph} is a description of the filter graph to apply to
225225 the stream. Use @code{-filters} to show all the available filters
226226 (including also sources and sinks).
227+
228+See also the @option{-filter_complex} option if you want to create filter graphs
229+with multiple inputs and/or outputs.
227230 @item -pre[:@var{stream_specifier}] @var{preset_name} (@emph{output,per-stream})
228231 Specify the preset for matching stream(s).
229232
@@ -522,7 +525,7 @@ Synchronize read on input. · 292 unmodified lines
522525 @section Advanced options
523526
524527 @table @option
525−@item -map [-]@var{input_file_id}[:@var{stream_specifier}][,@var{sync_file_id}[:@var{stream_specifier}]] (@emph{output})
528+@item -map [-]@var{input_file_id}[:@var{stream_specifier}][,@var{sync_file_id}[:@var{stream_specifier}]] | @var{[linklabel]} (@emph{output})
526529
527530 Designate one or more input streams as a source for the output file. Each input
528531 stream is identified by the input file index @var{input_file_id} and
@@ -538,6 +541,10 @@ the source for output stream 1, etc. · 9 unmodified lines
538541 A @code{-} character before the stream identifier creates a "negative" mapping.
539542 It disables matching streams from already created mappings.
540543
544+An alternative @var{[linklabel]} form will map outputs from complex filter
545+graphs (see the @option{-filter_complex} option) to the output file.
546+@var{linklabel} must correspond to a defined output link label in the graph.
547+
541548 For example, to map ALL streams from the first input file to output
542549 @example
543550 ffmpeg -i INPUT -map 0 output
@@ -832,6 +839,44 @@ Specify Timecode for writing. @var{SEP} is ':' for non drop timecode and ';' · 288 unmodified lines
832839 @example
833840 ffmpeg -i input.mpg -timecode 01:02:03.04 -r 30000/1001 -s ntsc output.mpg
834841 @end example
842+
843+@item -filter_complex @var{filtergraph} (@emph{global})
844+Define a complex filter graph, i.e. one with arbitrary number of inputs and/or
845+outputs. For simple graphs -- those with one input and one output of the same
846+type -- see the @option{-filter} options. @var{filtergraph} is a description of
847+the filter graph, as described in @ref{Filtergraph syntax}.
848+
849+Input link labels must refer to input streams using the
850+@code{[file_index:stream_specifier]} syntax (i.e. the same as @option{-map}
851+uses). If @var{stream_specifier} matches multiple streams, the first one will be
852+used. An unlabeled input will be connected to the first unused input stream of
853+the matching type.
854+
855+Output link labels are referred to with @option{-map}. Unlabeled outputs are
856+added to the first output file.
857+
858+For example, to overlay an image over video
859+@example
860+ffmpeg -i video.mkv -i image.png -filter_complex '[0:v][1:v]overlay[out]' -map
861+'[out]' out.mkv
862+@end example
863+Here @code{[0:v]} refers to the first video stream in the first input file,
864+which is linked to the first (main) input of the overlay filter. Similarly the
865+first video stream in the second input is linked to the second (overlay) input
866+of overlay.
867+
868+Assuming there is only one video stream in each input file, we can omit input
869+labels, so the above is equivalent to
870+@example
871+ffmpeg -i video.mkv -i image.png -filter_complex 'overlay[out]' -map
872+'[out]' out.mkv
873+@end example
874+
875+Furthermore we can omit the output label and the single output from the filter
876+graph will be added to the output file automatically, so we can simply write
877+@example
878+ffmpeg -i video.mkv -i image.png -filter_complex 'overlay' out.mkv
879+@end example
835880 @end table
836881
837882 @section Preset files
doc/filters.texi+1−0
@@ -14,6 +14,7 @@ number of input and output pads of the filter. · 13 unmodified lines
1414 A filter with no input pads is called a "source", a filter with no
1515 output pads is called a "sink".
1616
17+@anchor{Filtergraph syntax}
1718 @section Filtergraph syntax
1819
1920 A filtergraph can be represented using a textual representation, which
ffmpeg.c+864−352
@@ -108,6 +108,7 @@ typedef struct StreamMap { · 107 unmodified lines
108108 int stream_index;
109109 int sync_file_index;
110110 int sync_stream_index;
111+ char *linklabel; /** name of an output link, for mapping lavfi outputs */
111112 } StreamMap;
112113
113114 typedef struct {
@@ -175,6 +176,33 @@ static unsigned int allocated_async_buf_size; · 61 unmodified lines
175176
176177 #define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
177178
179+typedef struct InputFilter {
180+ AVFilterContext *filter;
181+ struct InputStream *ist;
182+ struct FilterGraph *graph;
183+} InputFilter;
184+
185+typedef struct OutputFilter {
186+ AVFilterContext *filter;
187+ struct OutputStream *ost;
188+ struct FilterGraph *graph;
189+
190+ /* temporary storage until stream maps are processed */
191+ AVFilterInOut *out_tmp;
192+} OutputFilter;
193+
194+typedef struct FilterGraph {
195+ int index;
196+ const char *graph_desc;
197+
198+ AVFilterGraph *graph;
199+
200+ InputFilter **inputs;
201+ int nb_inputs;
202+ OutputFilter **outputs;
203+ int nb_outputs;
204+} FilterGraph;
205+
178206 typedef struct FrameBuffer {
179207 uint8_t *base[4];
180208 uint8_t *data[4];
@@ -195,7 +223,6 @@ typedef struct InputStream { · 14 unmodified lines
195223 int decoding_needed; /* true if the packets must be decoded in 'raw_fifo' */
196224 AVCodec *dec;
197225 AVFrame *decoded_frame;
198− AVFrame *filtered_frame;
199226
200227 int64_t start; /* time when read started */
201228 /* predicted dts of the next packet read for this stream or (when there are
@@ -211,9 +238,18 @@ typedef struct InputStream { · 9 unmodified lines
211238 int showed_multi_packet_warning;
212239 AVDictionary *opts;
213240
241+ int resample_height;
242+ int resample_width;
243+ int resample_pix_fmt;
244+
214245 /* a pool of free buffers for decoded data */
215246 FrameBuffer *buffer_pool;
216247 int dr1;
248+
249+ /* decoded data from this stream goes into all those filters
250+ * currently video only */
251+ InputFilter **filters;
252+ int nb_filters;
217253 } InputStream;
218254
219255 typedef struct InputFile {
@@ -242,17 +278,15 @@ typedef struct OutputStream { · 22 unmodified lines
242278 AVCodec *enc;
243279 int64_t max_frames;
244280 AVFrame *output_frame;
281+ AVFrame *filtered_frame;
245282
246283 /* video only */
247− int video_resample;
248− int resample_height;
249− int resample_width;
250− int resample_pix_fmt;
251284 AVRational frame_rate;
252285 int force_fps;
253286 int top_field_first;
254287
255288 float frame_aspect_ratio;
289+ float last_quality;
256290
257291 /* forced key frames */
258292 int64_t *forced_kf_pts;
@@ -272,10 +306,8 @@ typedef struct OutputStream { · 13 unmodified lines
272306
273307 SwrContext *swr;
274308
275− AVFilterContext *output_video_filter;
276− AVFilterContext *input_video_filter;
309+ OutputFilter *filter;
277310 char *avfilter;
278− AVFilterGraph *graph;
279311
280312 int64_t sws_flags;
281313 int64_t swr_dither_method;
@@ -285,6 +317,8 @@ typedef struct OutputStream { · 3 unmodified lines
285317 int stream_copy;
286318 const char *attachment_filename;
287319 int copy_initial_nonkeyframes;
320+
321+ enum PixelFormat pix_fmts[2];
288322 } OutputStream;
289323
290324
@@ -304,15 +338,18 @@ typedef struct OutputFile { · 13 unmodified lines
304338 uint64_t limit_filesize; /* filesize limit expressed in bytes */
305339 } OutputFile;
306340
307−static InputStream *input_streams = NULL;
308−static int nb_input_streams = 0;
309−static InputFile *input_files = NULL;
310−static int nb_input_files = 0;
341+static InputStream **input_streams = NULL;
342+static int nb_input_streams = 0;
343+static InputFile **input_files = NULL;
344+static int nb_input_files = 0;
311345
312−static OutputStream *output_streams = NULL;
313−static int nb_output_streams = 0;
314−static OutputFile *output_files = NULL;
315−static int nb_output_files = 0;
346+static OutputStream **output_streams = NULL;
347+static int nb_output_streams = 0;
348+static OutputFile **output_files = NULL;
349+static int nb_output_files = 0;
350+
351+static FilterGraph **filtergraphs;
352+int nb_filtergraphs;
316353
317354 typedef struct OptionsContext {
318355 /* input/output options */
@@ -457,6 +494,7 @@ static void reset_options(OptionsContext *o, int is_input) · 138 unmodified lines
457494 {
458495 const OptionDef *po = options;
459496 OptionsContext bak= *o;
497+ int i;
460498
461499 /* all OPT_SPEC and OPT_STRING can be freed in generic way */
462500 while (po->name) {
@@ -477,6 +515,8 @@ static void reset_options(OptionsContext *o, int is_input) · 14 unmodified lines
477515 po++;
478516 }
479517
518+ for (i = 0; i < o->nb_stream_maps; i++)
519+ av_freep(&o->stream_maps[i].linklabel);
480520 av_freep(&o->stream_maps);
481521 av_freep(&o->audio_channel_maps);
482522 av_freep(&o->streamid_map);
@@ -627,20 +667,64 @@ static void filter_release_buffer(AVFilterBuffer *fb) · 144 unmodified lines
627667 unref_buffer(buf->ist, buf);
628668 }
629669
630−static int configure_video_filters(InputStream *ist, OutputStream *ost)
670+static void choose_pixel_fmt(AVStream *st, AVCodec *codec)
631671 {
672+ if (codec && codec->pix_fmts) {
673+ const enum PixelFormat *p = codec->pix_fmts;
674+ int has_alpha= av_pix_fmt_descriptors[st->codec->pix_fmt].nb_components % 2 == 0;
675+ enum PixelFormat best= PIX_FMT_NONE;
676+ if (st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
677+ if (st->codec->codec_id == CODEC_ID_MJPEG) {
678+ p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_NONE };
679+ } else if (st->codec->codec_id == CODEC_ID_LJPEG) {
680+ p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ444P, PIX_FMT_YUV420P,
681+ PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_BGRA, PIX_FMT_NONE };
682+ }
683+ }
684+ for (; *p != PIX_FMT_NONE; p++) {
685+ best= avcodec_find_best_pix_fmt2(best, *p, st->codec->pix_fmt, has_alpha, NULL);
686+ if (*p == st->codec->pix_fmt)
687+ break;
688+ }
689+ if (*p == PIX_FMT_NONE) {
690+ if (st->codec->pix_fmt != PIX_FMT_NONE)
691+ av_log(NULL, AV_LOG_WARNING,
692+ "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n",
693+ av_pix_fmt_descriptors[st->codec->pix_fmt].name,
694+ codec->name,
695+ av_pix_fmt_descriptors[best].name);
696+ st->codec->pix_fmt = best;
697+ }
698+ }
699+}
700+
701+static const enum PixelFormat *choose_pixel_fmts(OutputStream *ost)
702+{
703+ if (ost->st->codec->pix_fmt != PIX_FMT_NONE) {
704+ ost->pix_fmts[0] = ost->st->codec->pix_fmt;
705+ return ost->pix_fmts;
706+ } else if (ost->enc->pix_fmts)
707+ return ost->enc->pix_fmts;
708+ else
709+ return NULL;
710+}
711+
712+static int configure_video_filters(FilterGraph *fg)
713+{
714+ InputStream *ist = fg->inputs[0]->ist;
715+ OutputStream *ost = fg->outputs[0]->ost;
632716 AVFilterContext *last_filter, *filter;
633717 /** filter graph containing all filters including input & output */
634718 AVCodecContext *codec = ost->st->codec;
635− AVCodecContext *icodec = ist->st->codec;
636− enum PixelFormat pix_fmts[] = { codec->pix_fmt, PIX_FMT_NONE };
719+ enum PixelFormat *pix_fmts = choose_pixel_fmts(ost);
637720 AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
638721 AVRational sample_aspect_ratio;
639722 char args[255];
640723 int ret;
641724
642− ost->graph = avfilter_graph_alloc();
643− if (!ost->graph)
725+ avfilter_graph_free(&fg->graph);
726+ fg->graph = avfilter_graph_alloc();
727+ if (!fg->graph)
644728 return AVERROR(ENOMEM);
645729
646730 if (ist->st->sample_aspect_ratio.num) {
@@ -650,34 +734,35 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost) · 3 unmodified lines
650734
651735 snprintf(args, 255, "%d:%d:%d:%d:%d:%d:%d:flags=%d", ist->st->codec->width,
652736 ist->st->codec->height, ist->st->codec->pix_fmt, 1, AV_TIME_BASE,
653− sample_aspect_ratio.num, sample_aspect_ratio.den, SWS_BILINEAR + ((icodec->flags&CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0));
737+ sample_aspect_ratio.num, sample_aspect_ratio.den, SWS_BILINEAR + ((ist->st->codec->flags&CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0));
654738
655− ret = avfilter_graph_create_filter(&ost->input_video_filter, avfilter_get_by_name("buffer"),
656− "src", args, NULL, ost->graph);
739+ ret = avfilter_graph_create_filter(&fg->inputs[0]->filter,
740+ avfilter_get_by_name("buffer"),
741+ "src", args, NULL, fg->graph);
657742 if (ret < 0)
658743 return ret;
659744
660745 #if FF_API_OLD_VSINK_API
661− ret = avfilter_graph_create_filter(&ost->output_video_filter, avfilter_get_by_name("buffersink"),
662− "out", NULL, pix_fmts, ost->graph);
746+ ret = avfilter_graph_create_filter(&fg->outputs[0]->filter, avfilter_get_by_name("buffersink"),
747+ "out", NULL, pix_fmts, fg->graph);
663748 #else
664749 buffersink_params->pixel_fmts = pix_fmts;
665− ret = avfilter_graph_create_filter(&ost->output_video_filter, avfilter_get_by_name("buffersink"),
666− "out", NULL, buffersink_params, ost->graph);
750+ ret = avfilter_graph_create_filter(&fg->outputs[0]->filter, avfilter_get_by_name("buffersink"),
751+ "out", NULL, buffersink_params, fg->graph);
667752 #endif
668753 av_freep(&buffersink_params);
669754
670755 if (ret < 0)
671756 return ret;
672− last_filter = ost->input_video_filter;
757+ last_filter = fg->inputs[0]->filter;
673758
674− if (codec->width != icodec->width || codec->height != icodec->height) {
759+ if (codec->width || codec->height) {
675760 snprintf(args, 255, "%d:%d:flags=0x%X",
676761 codec->width,
677762 codec->height,
678763 (unsigned)ost->sws_flags);
679764 if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
680− NULL, args, NULL, ost->graph)) < 0)
765+ NULL, args, NULL, fg->graph)) < 0)
681766 return ret;
682767 if ((ret = avfilter_link(last_filter, 0, filter, 0)) < 0)
683768 return ret;
@@ -685,7 +770,7 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost) · 1 unmodified line
685770 }
686771
687772 snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags);
688− ost->graph->scale_sws_opts = av_strdup(args);
773+ fg->graph->scale_sws_opts = av_strdup(args);
689774
690775 if (ost->avfilter) {
691776 AVFilterInOut *outputs = avfilter_inout_alloc();
@@ -697,31 +782,258 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost) · 5 unmodified lines
697782 outputs->next = NULL;
698783
699784 inputs->name = av_strdup("out");
700− inputs->filter_ctx = ost->output_video_filter;
785+ inputs->filter_ctx = fg->outputs[0]->filter;
701786 inputs->pad_idx = 0;
702787 inputs->next = NULL;
703788
704− if ((ret = avfilter_graph_parse(ost->graph, ost->avfilter, &inputs, &outputs, NULL)) < 0)
789+ if ((ret = avfilter_graph_parse(fg->graph, ost->avfilter, &inputs, &outputs, NULL)) < 0)
705790 return ret;
706791 av_freep(&ost->avfilter);
707792 } else {
708− if ((ret = avfilter_link(last_filter, 0, ost->output_video_filter, 0)) < 0)
793+ if ((ret = avfilter_link(last_filter, 0, fg->outputs[0]->filter, 0)) < 0)
709794 return ret;
710795 }
711796
712− if ((ret = avfilter_graph_config(ost->graph, NULL)) < 0)
797+ if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0)
713798 return ret;
714799
715− codec->width = ost->output_video_filter->inputs[0]->w;
716− codec->height = ost->output_video_filter->inputs[0]->h;
717− codec->sample_aspect_ratio = ost->st->sample_aspect_ratio =
718− ost->frame_aspect_ratio ? // overridden by the -aspect cli option
719− av_d2q(ost->frame_aspect_ratio * codec->height/codec->width, 255) :
720− ost->output_video_filter->inputs[0]->sample_aspect_ratio;
800+ ost->filter = fg->outputs[0];
721801
722802 return 0;
723803 }
724804
805+static FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost)
806+{
807+ FilterGraph *fg = av_mallocz(sizeof(*fg));
808+
809+ if (!fg)
810+ exit_program(1);
811+ fg->index = nb_filtergraphs;
812+
813+ fg->outputs = grow_array(fg->outputs, sizeof(*fg->outputs), &fg->nb_outputs,
814+ fg->nb_outputs + 1);
815+ if (!(fg->outputs[0] = av_mallocz(sizeof(*fg->outputs[0]))))
816+ exit_program(1);
817+ fg->outputs[0]->ost = ost;
818+ fg->outputs[0]->graph = fg;
819+
820+ fg->inputs = grow_array(fg->inputs, sizeof(*fg->inputs), &fg->nb_inputs,
821+ fg->nb_inputs + 1);
822+ if (!(fg->inputs[0] = av_mallocz(sizeof(*fg->inputs[0]))))
823+ exit_program(1);
824+ fg->inputs[0]->ist = ist;
825+ fg->inputs[0]->graph = fg;
826+
827+ ist->filters = grow_array(ist->filters, sizeof(*ist->filters),
828+ &ist->nb_filters, ist->nb_filters + 1);
829+ ist->filters[ist->nb_filters - 1] = fg->inputs[0];
830+
831+ filtergraphs = grow_array(filtergraphs, sizeof(*filtergraphs),
832+ &nb_filtergraphs, nb_filtergraphs + 1);
833+ filtergraphs[nb_filtergraphs - 1] = fg;
834+
835+ return fg;
836+}
837+
838+static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
839+{
840+ InputStream *ist;
841+ enum AVMediaType type = in->filter_ctx->input_pads[in->pad_idx].type;
842+ int i;
843+
844+ // TODO: support other filter types
845+ if (type != AVMEDIA_TYPE_VIDEO) {
846+ av_log(NULL, AV_LOG_FATAL, "Only video filters supported currently.\n");
847+ exit_program(1);
848+ }
849+
850+ if (in->name) {
851+ AVFormatContext *s;
852+ AVStream *st = NULL;
853+ char *p;
854+ int file_idx = strtol(in->name, &p, 0);
855+
856+ if (file_idx < 0 || file_idx > nb_input_files) {
857+ av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtegraph description %s.\n",
858+ file_idx, fg->graph_desc);
859+ exit_program(1);
860+ }
861+ s = input_files[file_idx]->ctx;
862+
863+ for (i = 0; i < s->nb_streams; i++) {
864+ if (s->streams[i]->codec->codec_type != type)
865+ continue;
866+ if (check_stream_specifier(s, s->streams[i], *p == ':' ? p + 1 : p) == 1) {
867+ st = s->streams[i];
868+ break;
869+ }
870+ }
871+ if (!st) {
872+ av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s "
873+ "matches no streams.\n", p, fg->graph_desc);
874+ exit_program(1);
875+ }
876+ ist = input_streams[input_files[file_idx]->ist_index + st->index];
877+ } else {
878+ /* find the first unused stream of corresponding type */
879+ for (i = 0; i < nb_input_streams; i++) {
880+ ist = input_streams[i];
881+ if (ist->st->codec->codec_type == type && ist->discard)
882+ break;
883+ }
884+ if (i == nb_input_streams) {
885+ av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for "
886+ "unlabeled input pad %d on filter %s", in->pad_idx,
887+ in->filter_ctx->name);
888+ exit_program(1);
889+ }
890+ }
891+ ist->discard = 0;
892+ ist->decoding_needed = 1;
893+ ist->st->discard = AVDISCARD_NONE;
894+
895+ fg->inputs = grow_array(fg->inputs, sizeof(*fg->inputs),
896+ &fg->nb_inputs, fg->nb_inputs + 1);
897+ if (!(fg->inputs[fg->nb_inputs - 1] = av_mallocz(sizeof(*fg->inputs[0]))))
898+ exit_program(1);
899+ fg->inputs[fg->nb_inputs - 1]->ist = ist;
900+ fg->inputs[fg->nb_inputs - 1]->graph = fg;
901+
902+ ist->filters = grow_array(ist->filters, sizeof(*ist->filters),
903+ &ist->nb_filters, ist->nb_filters + 1);
904+ ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1];
905+}
906+
907+static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
908+{
909+ AVCodecContext *codec = ofilter->ost->st->codec;
910+ AVFilterContext *last_filter = out->filter_ctx;
911+ int pad_idx = out->pad_idx;
912+ int ret;
913+ enum PixelFormat *pix_fmts = choose_pixel_fmts(ofilter->ost);
914+ AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
915+
916+#if FF_API_OLD_VSINK_API
917+ ret = avfilter_graph_create_filter(&ofilter->filter, avfilter_get_by_name("buffersink"),
918+ "out", NULL, pix_fmts, fg->graph);
919+#else
920+ buffersink_params->pixel_fmts = pix_fmts;
921+ ret = avfilter_graph_create_filter(&ofilter->filter, avfilter_get_by_name("buffersink"),
922+ "out", NULL, buffersink_params, fg->graph);
923+#endif
924+ av_freep(&buffersink_params);
925+
926+ if (ret < 0)
927+ return ret;
928+
929+ if (codec->width || codec->height) {
930+ char args[255];
931+ snprintf(args, sizeof(args), "%d:%d:flags=0x%X",
932+ codec->width,
933+ codec->height,
934+ (unsigned)ofilter->ost->sws_flags);
935+ if ((ret = avfilter_graph_create_filter(&last_filter, avfilter_get_by_name("scale"),
936+ NULL, args, NULL, fg->graph)) < 0)
937+ return ret;
938+ if ((ret = avfilter_link(out->filter_ctx, out->pad_idx, last_filter, 0)) < 0)
939+ return ret;
940+ pad_idx = 0;
941+ }
942+
943+ if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
944+ return ret;
945+
946+ return 0;
947+}
948+
949+static int configure_complex_filter(FilterGraph *fg)
950+{
951+ AVFilterInOut *inputs, *outputs, *cur;
952+ int ret, i, init = !fg->graph;
953+
954+ avfilter_graph_free(&fg->graph);
955+ if (!(fg->graph = avfilter_graph_alloc()))
956+ return AVERROR(ENOMEM);
957+
958+ if ((ret = avfilter_graph_parse2(fg->graph, fg->graph_desc, &inputs, &outputs)) < 0)
959+ return ret;
960+
961+ for (cur = inputs; init && cur; cur = cur->next)
962+ init_input_filter(fg, cur);
963+
964+ for (cur = inputs, i = 0; cur; cur = cur->next, i++) {
965+ InputFilter *ifilter = fg->inputs[i];
966+ InputStream *ist = ifilter->ist;
967+ AVRational sar;
968+ char args[255];
969+
970+ sar = ist->st->sample_aspect_ratio.num ? ist->st->sample_aspect_ratio :
971+ ist->st->codec->sample_aspect_ratio;
972+ snprintf(args, sizeof(args), "%d:%d:%d:%d:%d:%d:%d", ist->st->codec->width,
973+ ist->st->codec->height, ist->st->codec->pix_fmt, 1, AV_TIME_BASE,
974+ sar.num, sar.den);
975+
976+ if ((ret = avfilter_graph_create_filter(&ifilter->filter,
977+ avfilter_get_by_name("buffer"), cur->name,
978+ args, NULL, fg->graph)) < 0)
979+ return ret;
980+ if ((ret = avfilter_link(ifilter->filter, 0,
981+ cur->filter_ctx, cur->pad_idx)) < 0)
982+ return ret;
983+ }
984+ avfilter_inout_free(&inputs);
985+
986+ if (!init) {
987+ /* we already know the mappings between lavfi outputs and output streams,
988+ * so we can finish the setup */
989+ for (cur = outputs, i = 0; cur; cur = cur->next, i++)
990+ configure_output_filter(fg, fg->outputs[i], cur);
991+ avfilter_inout_free(&outputs);
992+
993+ if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0)
994+ return ret;
995+ } else {
996+ /* wait until output mappings are processed */
997+ for (cur = outputs; cur;) {
998+ fg->outputs = grow_array(fg->outputs, sizeof(*fg->outputs),
999+ &fg->nb_outputs, fg->nb_outputs + 1);
1000+ if (!(fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0]))))
1001+ exit_program(1);
1002+ fg->outputs[fg->nb_outputs - 1]->graph = fg;
1003+ fg->outputs[fg->nb_outputs - 1]->out_tmp = cur;
1004+ cur = cur->next;
1005+ fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL;
1006+ }
1007+ }
1008+
1009+ return 0;
1010+}
1011+
1012+static int configure_complex_filters(void)
1013+{
1014+ int i, ret = 0;
1015+
1016+ for (i = 0; i < nb_filtergraphs; i++)
1017+ if (!filtergraphs[i]->graph &&
1018+ (ret = configure_complex_filter(filtergraphs[i])) < 0)
1019+ return ret;
1020+ return 0;
1021+}
1022+
1023+static int configure_filtergraph(FilterGraph *fg)
1024+{
1025+ return fg->graph_desc ? configure_complex_filter(fg) : configure_video_filters(fg);
1026+}
1027+
1028+static int ist_in_filtergraph(FilterGraph *fg, InputStream *ist)
1029+{
1030+ int i;
1031+ for (i = 0; i < fg->nb_inputs; i++)
1032+ if (fg->inputs[i]->ist == ist)
1033+ return 1;
1034+ return 0;
1035+}
1036+
7251037 static void term_exit(void)
7261038 {
7271039 av_log(NULL, AV_LOG_QUIET, "%s", "");
@@ -839,40 +1151,57 @@ static const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL }; · 111 unmodified lines
8391151
8401152 void av_noreturn exit_program(int ret)
8411153 {
842− int i;
1154+ int i, j;
1155+
1156+ for (i = 0; i < nb_filtergraphs; i++) {
1157+ avfilter_graph_free(&filtergraphs[i]->graph);
1158+ for (j = 0; j < filtergraphs[i]->nb_inputs; j++)
1159+ av_freep(&filtergraphs[i]->inputs[j]);
1160+ av_freep(&filtergraphs[i]->inputs);
1161+ for (j = 0; j < filtergraphs[i]->nb_outputs; j++)
1162+ av_freep(&filtergraphs[i]->outputs[j]);
1163+ av_freep(&filtergraphs[i]->outputs);
1164+ av_freep(&filtergraphs[i]);
1165+ }
1166+ av_freep(&filtergraphs);
8431167
8441168 /* close files */
8451169 for (i = 0; i < nb_output_files; i++) {
846− AVFormatContext *s = output_files[i].ctx;
1170+ AVFormatContext *s = output_files[i]->ctx;
8471171 if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
8481172 avio_close(s->pb);
8491173 avformat_free_context(s);
850− av_dict_free(&output_files[i].opts);
1174+ av_dict_free(&output_files[i]->opts);
1175+ av_freep(&output_files[i]);
8511176 }
8521177 for (i = 0; i < nb_output_streams; i++) {
853− AVBitStreamFilterContext *bsfc = output_streams[i].bitstream_filters;
1178+ AVBitStreamFilterContext *bsfc = output_streams[i]->bitstream_filters;
8541179 while (bsfc) {
8551180 AVBitStreamFilterContext *next = bsfc->next;
8561181 av_bitstream_filter_close(bsfc);
8571182 bsfc = next;
8581183 }
859− output_streams[i].bitstream_filters = NULL;
1184+ output_streams[i]->bitstream_filters = NULL;
8601185
861− if (output_streams[i].output_frame) {
862− AVFrame *frame = output_streams[i].output_frame;
1186+ if (output_streams[i]->output_frame) {
1187+ AVFrame *frame = output_streams[i]->output_frame;
8631188 if (frame->extended_data != frame->data)
8641189 av_freep(&frame->extended_data);
8651190 av_freep(&frame);
8661191 }
1192+ av_freep(&output_streams[i]->filtered_frame);
1193+ av_freep(&output_streams[i]);
8671194 }
8681195 for (i = 0; i < nb_input_files; i++) {
869− avformat_close_input(&input_files[i].ctx);
1196+ avformat_close_input(&input_files[i]->ctx);
1197+ av_freep(&input_files[i]);
8701198 }
8711199 for (i = 0; i < nb_input_streams; i++) {
872− av_freep(&input_streams[i].decoded_frame);
873− av_freep(&input_streams[i].filtered_frame);
874− av_dict_free(&input_streams[i].opts);
875− free_buffer_pool(&input_streams[i]);
1200+ av_freep(&input_streams[i]->decoded_frame);
1201+ av_dict_free(&input_streams[i]->opts);
1202+ free_buffer_pool(input_streams[i]);
1203+ av_freep(&input_streams[i]->filters);
1204+ av_freep(&input_streams[i]);
8761205 }
8771206
8781207 if (vstats_file)
@@ -981,41 +1310,10 @@ static void choose_sample_rate(AVStream *st, AVCodec *codec) · 102 unmodified lines
9811310 }
9821311 }
9831312
984−static void choose_pixel_fmt(AVStream *st, AVCodec *codec)
985−{
986− if (codec && codec->pix_fmts) {
987− const enum PixelFormat *p = codec->pix_fmts;
988− int has_alpha= av_pix_fmt_descriptors[st->codec->pix_fmt].nb_components % 2 == 0;
989− enum PixelFormat best= PIX_FMT_NONE;
990− if (st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
991− if (st->codec->codec_id == CODEC_ID_MJPEG) {
992− p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_NONE };
993− } else if (st->codec->codec_id == CODEC_ID_LJPEG) {
994− p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ444P, PIX_FMT_YUV420P,
995− PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_BGRA, PIX_FMT_NONE };
996− }
997− }
998− for (; *p != PIX_FMT_NONE; p++) {
999− best= avcodec_find_best_pix_fmt2(best, *p, st->codec->pix_fmt, has_alpha, NULL);
1000− if (*p == st->codec->pix_fmt)
1001− break;
1002− }
1003− if (*p == PIX_FMT_NONE) {
1004− if (st->codec->pix_fmt != PIX_FMT_NONE)
1005− av_log(NULL, AV_LOG_WARNING,
1006− "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n",
1007− av_pix_fmt_descriptors[st->codec->pix_fmt].name,
1008− codec->name,
1009− av_pix_fmt_descriptors[best].name);
1010− st->codec->pix_fmt = best;
1011− }
1012− }
1013−}
1014−
10151313 static double
10161314 get_sync_ipts(const OutputStream *ost, int64_t pts)
10171315 {
1018− OutputFile *of = &output_files[ost->file_index];
1316+ OutputFile *of = output_files[ost->file_index];
10191317 return (double)(pts - of->start_time) / AV_TIME_BASE;
10201318 }
10211319
@@ -1518,19 +1816,21 @@ static void do_video_stats(AVFormatContext *os, OutputStream *ost, · 496 unmodified lines
15181816
15191817
15201818 static void do_video_out(AVFormatContext *s, OutputStream *ost,
1521− InputStream *ist, AVFrame *in_picture)
1819+ AVFrame *in_picture, float quality)
15221820 {
15231821 int nb_frames, i, ret, format_video_sync;
15241822 AVCodecContext *enc;
15251823 double sync_ipts, delta;
15261824 double duration = 0;
15271825 int frame_size = 0;
1528− float quality = same_quant ? in_picture->quality
1529− : ost->st->codec->global_quality;
1826+ InputStream *ist = NULL;
1827+
1828+ if (ost->source_index >= 0)
1829+ ist = input_streams[ost->source_index];
15301830
15311831 enc = ost->st->codec;
15321832
1533− if (ist->st->start_time != AV_NOPTS_VALUE && ist->st->first_dts != AV_NOPTS_VALUE) {
1833+ if (ist && ist->st->start_time != AV_NOPTS_VALUE && ist->st->first_dts != AV_NOPTS_VALUE) {
15341834 duration = FFMAX(av_q2d(ist->st->time_base), av_q2d(ist->st->codec->time_base));
15351835 if(ist->st->r_frame_rate.num)
15361836 duration= FFMAX(duration, 1/av_q2d(ist->st->r_frame_rate));
@@ -1672,12 +1972,66 @@ static void do_video_out(AVFormatContext *s, OutputStream *ost, · 135 unmodified lines
16721972 ost->frame_number++;
16731973 }
16741974 if (vstats_filename && frame_size)
1675− do_video_stats(output_files[ost->file_index].ctx, ost, frame_size);
1975+ do_video_stats(output_files[ost->file_index]->ctx, ost, frame_size);
16761976 }
16771977
1678−static void print_report(OutputFile *output_files,
1679− OutputStream *ost_table, int nb_ostreams,
1680− int is_last_report, int64_t timer_start, int64_t cur_time)
1978+/* check for new output on any of the filtergraphs */
1979+static int poll_filters(void)
1980+{
1981+ AVFilterBufferRef *picref;
1982+ AVFrame *filtered_frame = NULL;
1983+ int i, ret;
1984+
1985+ for (i = 0; i < nb_output_streams; i++) {
1986+ OutputStream *ost = output_streams[i];
1987+ OutputFile *of = output_files[ost->file_index];
1988+
1989+ if (!ost->filter || ost->is_past_recording_time)
1990+ continue;
1991+
1992+ if (!ost->filtered_frame && !(ost->filtered_frame = avcodec_alloc_frame())) {
1993+ return AVERROR(ENOMEM);
1994+ } else
1995+ avcodec_get_frame_defaults(ost->filtered_frame);
1996+ filtered_frame = ost->filtered_frame;
1997+
1998+ while (avfilter_poll_frame(ost->filter->filter->inputs[0])) {
1999+ AVRational ist_pts_tb = ost->filter->filter->inputs[0]->time_base;
2000+ if ((ret = av_buffersink_get_buffer_ref(ost->filter->filter,
2001+ &picref,
2002+ 0)) < 0) {
2003+ av_log(NULL, AV_LOG_WARNING, "AV Filter told us it has a frame available but failed to output one\n");
2004+ return ret;
2005+ }
2006+ filtered_frame->pts = av_rescale_q(picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
2007+// if (ost->source_index >= 0)
2008+// *filtered_frame= *input_streams[ost->source_index]->decoded_frame; //for me_threshold
2009+
2010+ if (of->start_time && filtered_frame->pts < of->start_time)
2011+ return 0;
2012+
2013+ switch (ost->filter->filter->inputs[0]->type) {
2014+ case AVMEDIA_TYPE_VIDEO:
2015+ avfilter_fill_frame_from_video_buffer_ref(filtered_frame, picref);
2016+ if (!ost->frame_aspect_ratio)
2017+ ost->st->codec->sample_aspect_ratio = picref->video->sample_aspect_ratio;
2018+
2019+ do_video_out(of->ctx, ost, filtered_frame,
2020+ same_quant ? ost->last_quality :
2021+ ost->st->codec->global_quality);
2022+ break;
2023+ default:
2024+ // TODO support audio/subtitle filters
2025+ av_assert0(0);
2026+ }
2027+
2028+ avfilter_unref_buffer(picref);
2029+ }
2030+ }
2031+ return 0;
2032+}
2033+
2034+static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time)
16812035 {
16822036 char buf[1024];
16832037 OutputStream *ost;
@@ -1705,7 +2059,7 @@ static void print_report(OutputFile *output_files, · 21 unmodified lines
17052059 }
17062060
17072061
1708− oc = output_files[0].ctx;
2062+ oc = output_files[0]->ctx;
17092063
17102064 total_size = avio_size(oc->pb);
17112065 if (total_size < 0) { // FIXME improve avio_size() so it works with non seekable output too
@@ -1716,9 +2070,9 @@ static void print_report(OutputFile *output_files, · 4 unmodified lines
17162070
17172071 buf[0] = '\0';
17182072 vid = 0;
1719− for (i = 0; i < nb_ostreams; i++) {
2073+ for (i = 0; i < nb_output_streams; i++) {
17202074 float q = -1;
1721− ost = &ost_table[i];
2075+ ost = output_streams[i];
17222076 enc = ost->st->codec;
17232077 if (!ost->stream_copy && enc->coded_frame)
17242078 q = enc->coded_frame->quality / (float)FF_QP2LAMBDA;
@@ -1811,14 +2165,14 @@ static void print_report(OutputFile *output_files, · 86 unmodified lines
18112165 }
18122166 }
18132167
1814−static void flush_encoders(OutputStream *ost_table, int nb_ostreams)
2168+static void flush_encoders(void)
18152169 {
18162170 int i, ret;
18172171
1818− for (i = 0; i < nb_ostreams; i++) {
1819− OutputStream *ost = &ost_table[i];
2172+ for (i = 0; i < nb_output_streams; i++) {
2173+ OutputStream *ost = output_streams[i];
18202174 AVCodecContext *enc = ost->st->codec;
1821− AVFormatContext *os = output_files[ost->file_index].ctx;
2175+ AVFormatContext *os = output_files[ost->file_index]->ctx;
18222176 int stop_encoding = 0;
18232177
18242178 if (!ost->encoding_needed)
@@ -1899,8 +2253,8 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams) · 74 unmodified lines
18992253 */
19002254 static int check_output_constraints(InputStream *ist, OutputStream *ost)
19012255 {
1902− OutputFile *of = &output_files[ost->file_index];
1903− int ist_index = ist - input_streams;
2256+ OutputFile *of = output_files[ost->file_index];
2257+ int ist_index = input_files[ist->file_index]->ist_index + ist->st->index;
19042258
19052259 if (ost->source_index != ist_index)
19062260 return 0;
@@ -1920,7 +2274,7 @@ static int check_output_constraints(InputStream *ist, OutputStream *ost) · 13 unmodified lines
19202274
19212275 static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt)
19222276 {
1923− OutputFile *of = &output_files[ost->file_index];
2277+ OutputFile *of = output_files[ost->file_index];
19242278 int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base);
19252279 AVPicture pict;
19262280 AVPacket opkt;
@@ -1980,7 +2334,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p · 53 unmodified lines
19802334
19812335 static void rate_emu_sleep(InputStream *ist)
19822336 {
1983− if (input_files[ist->file_index].rate_emu) {
2337+ if (input_files[ist->file_index]->rate_emu) {
19842338 int64_t pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE);
19852339 int64_t now = av_gettime() - ist->start;
19862340 if (pts > now)
@@ -2091,11 +2445,11 @@ static int transcode_audio(InputStream *ist, AVPacket *pkt, int *got_output) · 104 unmodified lines
20912445 rate_emu_sleep(ist);
20922446
20932447 for (i = 0; i < nb_output_streams; i++) {
2094− OutputStream *ost = &output_streams[i];
2448+ OutputStream *ost = output_streams[i];
20952449
20962450 if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
20972451 continue;
2098− do_audio_out(output_files[ost->file_index].ctx, ost, ist, decoded_frame);
2452+ do_audio_out(output_files[ost->file_index]->ctx, ost, ist, decoded_frame);
20992453 }
21002454
21012455 return ret;
@@ -2105,9 +2459,10 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int · 3 unmodified lines
21052459 {
21062460 AVFrame *decoded_frame;
21072461 void *buffer_to_free = NULL;
2108− int i, ret = 0;
2462+ int i, ret = 0, resample_changed;
21092463 int64_t *best_effort_timestamp;
21102464 AVRational *frame_sample_aspect;
2465+ float quality;
21112466
21122467 if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame()))
21132468 return AVERROR(ENOMEM);
@@ -2125,6 +2480,7 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int · 11 unmodified lines
21252480 if (ret < 0)
21262481 return ret;
21272482
2483+ quality = same_quant ? decoded_frame->quality : 0;
21282484 if (!*got_output) {
21292485 /* no picture yet */
21302486 return ret;
@@ -2138,75 +2494,66 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int · 7 unmodified lines
21382494
21392495 pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free);
21402496
2141− frame_sample_aspect= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "sample_aspect_ratio");
2142− for(i=0;i<nb_output_streams;i++) {
2143− OutputStream *ost = ost = &output_streams[i];
2144− if(check_output_constraints(ist, ost) && ost->encoding_needed){
2145− int changed = ist->st->codec->width != ost->input_video_filter->outputs[0]->w
2146− || ist->st->codec->height != ost->input_video_filter->outputs[0]->h
2147− || ist->st->codec->pix_fmt != ost->input_video_filter->outputs[0]->format;
2148− if (!frame_sample_aspect->num)
2149− *frame_sample_aspect = ist->st->sample_aspect_ratio;
2150− decoded_frame->pts = ist->pts;
2151− if (ist->dr1 && decoded_frame->type==FF_BUFFER_TYPE_USER && !changed) {
2152− FrameBuffer *buf = decoded_frame->opaque;
2153− AVFilterBufferRef *fb = avfilter_get_video_buffer_ref_from_arrays(
2154− decoded_frame->data, decoded_frame->linesize,
2155− AV_PERM_READ | AV_PERM_PRESERVE,
2156− ist->st->codec->width, ist->st->codec->height,
2157− ist->st->codec->pix_fmt);
2158−
2159− avfilter_copy_frame_props(fb, decoded_frame);
2160− fb->buf->priv = buf;
2161− fb->buf->free = filter_release_buffer;
2162−
2163− buf->refcount++;
2164− av_buffersrc_buffer(ost->input_video_filter, fb);
2165− } else
2166− if((av_vsrc_buffer_add_frame(ost->input_video_filter, decoded_frame, AV_VSRC_BUF_FLAG_OVERWRITE)) < 0){
2167− av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n");
2168− exit_program(1);
2169− }
2170− }
2171− }
2172−
21732497 rate_emu_sleep(ist);
21742498
21752499 if (ist->st->sample_aspect_ratio.num)
21762500 decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
21772501
2178− for (i = 0; i < nb_output_streams; i++) {
2179− OutputStream *ost = &output_streams[i];
2180−
2181− if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
2182− continue;
2183−
2184− while (av_buffersink_poll_frame(ost->output_video_filter)) {
2185− AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base;
2186− AVFrame *filtered_frame;
2187− AVFilterBufferRef *picref;
2188−
2189− if (av_buffersink_get_buffer_ref(ost->output_video_filter, &picref, 0) < 0){
2190− av_log(NULL, AV_LOG_WARNING, "AV Filter told us it has a frame available but failed to output one\n");
2191− goto cont;
2192− }
2193− if (!ist->filtered_frame && !(ist->filtered_frame = avcodec_alloc_frame())) {
2194− ret = AVERROR(ENOMEM);
2195− goto fail;
2502+ resample_changed = ist->resample_width != decoded_frame->width ||
2503+ ist->resample_height != decoded_frame->height ||
2504+ ist->resample_pix_fmt != decoded_frame->format;
2505+ if (resample_changed) {
2506+ av_log(NULL, AV_LOG_INFO,
2507+ "Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n",
2508+ ist->file_index, ist->st->index,
2509+ ist->resample_width, ist->resample_height, av_get_pix_fmt_name(ist->resample_pix_fmt),
2510+ decoded_frame->width, decoded_frame->height, av_get_pix_fmt_name(decoded_frame->format));
2511+
2512+ ist->resample_width = decoded_frame->width;
2513+ ist->resample_height = decoded_frame->height;
2514+ ist->resample_pix_fmt = decoded_frame->format;
2515+
2516+ for (i = 0; i < nb_filtergraphs; i++)
2517+ if (ist_in_filtergraph(filtergraphs[i], ist) &&
2518+ configure_filtergraph(filtergraphs[i]) < 0) {
2519+ av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n");
2520+ exit_program(1);
21962521 }
2197− filtered_frame = ist->filtered_frame;
2198− *filtered_frame= *decoded_frame; //for me_threshold
2199− avfilter_fill_frame_from_video_buffer_ref(filtered_frame, picref);
2200− filtered_frame->pts = av_rescale_q(picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
2201− if (!ost->frame_aspect_ratio)
2202− ost->st->codec->sample_aspect_ratio = picref->video->sample_aspect_ratio;
2203− do_video_out(output_files[ost->file_index].ctx, ost, ist, filtered_frame);
2204− cont:
2205− avfilter_unref_buffer(picref);
2522+ }
2523+
2524+ frame_sample_aspect= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "sample_aspect_ratio");
2525+ for (i = 0; i < ist->nb_filters; i++) {
2526+ int changed = ist->st->codec->width != ist->filters[i]->filter->outputs[0]->w
2527+ || ist->st->codec->height != ist->filters[i]->filter->outputs[0]->h
2528+ || ist->st->codec->pix_fmt != ist->filters[i]->filter->outputs[0]->format;
2529+ // XXX what an ugly hack
2530+ if (ist->filters[i]->graph->nb_outputs == 1)
2531+ ist->filters[i]->graph->outputs[0]->ost->last_quality = quality;
2532+
2533+ if (!frame_sample_aspect->num)
2534+ *frame_sample_aspect = ist->st->sample_aspect_ratio;
2535+ if (ist->dr1 && decoded_frame->type==FF_BUFFER_TYPE_USER && !changed) {
2536+ FrameBuffer *buf = decoded_frame->opaque;
2537+ AVFilterBufferRef *fb = avfilter_get_video_buffer_ref_from_arrays(
2538+ decoded_frame->data, decoded_frame->linesize,
2539+ AV_PERM_READ | AV_PERM_PRESERVE,
2540+ ist->st->codec->width, ist->st->codec->height,
2541+ ist->st->codec->pix_fmt);
2542+
2543+ avfilter_copy_frame_props(fb, decoded_frame);
2544+ fb->buf->priv = buf;
2545+ fb->buf->free = filter_release_buffer;
2546+
2547+ buf->refcount++;
2548+ av_buffersrc_buffer(ist->filters[i]->filter, fb);
2549+ } else
2550+ if(av_vsrc_buffer_add_frame(ist->filters[i]->filter, decoded_frame,AV_VSRC_BUF_FLAG_OVERWRITE)<0) {
2551+ av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n");
2552+ exit_program(1);
22062553 }
2554+
22072555 }
22082556
2209−fail:
22102557 av_free(buffer_to_free);
22112558 return ret;
22122559 }
@@ -2224,12 +2571,12 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) · 11 unmodified lines
22242571 rate_emu_sleep(ist);
22252572
22262573 for (i = 0; i < nb_output_streams; i++) {
2227− OutputStream *ost = &output_streams[i];
2574+ OutputStream *ost = output_streams[i];
22282575
22292576 if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
22302577 continue;
22312578
2232− do_subtitle_out(output_files[ost->file_index].ctx, ost, ist, &subtitle, pkt->pts);
2579+ do_subtitle_out(output_files[ost->file_index]->ctx, ost, ist, &subtitle, pkt->pts);
22332580 }
22342581
22352582 avsubtitle_free(&subtitle);
@@ -2237,9 +2584,7 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output) · 1 unmodified line
22372584 }
22382585
22392586 /* pkt = NULL means EOF (needed to flush decoder buffers) */
2240−static int output_packet(InputStream *ist,
2241− OutputStream *ost_table, int nb_ostreams,
2242− const AVPacket *pkt)
2587+static int output_packet(InputStream *ist, const AVPacket *pkt)
22432588 {
22442589 int ret = 0, i;
22452590 int got_output;
@@ -2356,8 +2701,8 @@ static int output_packet(InputStream *ist, · 110 unmodified lines
23562701 ist->pts = ist->dts;
23572702 ist->next_pts = ist->next_dts;
23582703 }
2359− for (i = 0; pkt && i < nb_ostreams; i++) {
2360− OutputStream *ost = &ost_table[i];
2704+ for (i = 0; pkt && i < nb_output_streams; i++) {
2705+ OutputStream *ost = output_streams[i];
23612706
23622707 if (!check_output_constraints(ist, ost) || ost->encoding_needed)
23632708 continue;
@@ -2368,18 +2713,18 @@ static int output_packet(InputStream *ist, · 4 unmodified lines
23682713 return 0;
23692714 }
23702715
2371−static void print_sdp(OutputFile *output_files, int n)
2716+static void print_sdp(void)
23722717 {
23732718 char sdp[2048];
23742719 int i;
2375− AVFormatContext **avc = av_malloc(sizeof(*avc) * n);
2720+ AVFormatContext **avc = av_malloc(sizeof(*avc) * nb_output_files);
23762721
23772722 if (!avc)
23782723 exit_program(1);
2379− for (i = 0; i < n; i++)
2380− avc[i] = output_files[i].ctx;
2724+ for (i = 0; i < nb_output_files; i++)
2725+ avc[i] = output_files[i]->ctx;
23812726
2382− av_sdp_create(avc, n, sdp, sizeof(sdp));
2727+ av_sdp_create(avc, nb_output_files, sdp, sizeof(sdp));
23832728 printf("SDP:\n%s\n", sdp);
23842729 fflush(stdout);
23852730 av_freep(&avc);
@@ -2430,11 +2775,10 @@ static void get_default_channel_layouts(OutputStream *ost, InputStream *ist) · 44 unmodified lines
24302775 }
24312776
24322777
2433−static int init_input_stream(int ist_index, OutputStream *output_streams, int nb_output_streams,
2434− char *error, int error_len)
2778+static int init_input_stream(int ist_index, char *error, int error_len)
24352779 {
2436− InputStream *ist = &input_streams[ist_index];
24372780 int i;
2781+ InputStream *ist = input_streams[ist_index];
24382782
24392783 if (ist->decoding_needed) {
24402784 AVCodec *codec = ist->dec;
@@ -2463,7 +2807,7 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb · 22 unmodified lines
24632807
24642808 if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
24652809 for (i = 0; i < nb_output_streams; i++) {
2466− OutputStream *ost = &output_streams[i];
2810+ OutputStream *ost = output_streams[i];
24672811 if (ost->source_index == ist_index) {
24682812 if (!ist->st->codec->channel_layout || !ost->st->codec->channel_layout)
24692813 get_default_channel_layouts(ost, ist);
@@ -2481,8 +2825,24 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb · 11 unmodified lines
24812825 return 0;
24822826 }
24832827
2484−static int transcode_init(OutputFile *output_files, int nb_output_files,
2485− InputFile *input_files, int nb_input_files)
2828+static InputStream *get_input_stream(OutputStream *ost)
2829+{
2830+ if (ost->source_index >= 0)
2831+ return input_streams[ost->source_index];
2832+
2833+ if (ost->filter) {
2834+ FilterGraph *fg = ost->filter->graph;
2835+ int i;
2836+
2837+ for (i = 0; i < fg->nb_inputs; i++)
2838+ if (fg->inputs[i]->ist->st->codec->codec_type == ost->st->codec->codec_type)
2839+ return fg->inputs[i]->ist;
2840+ }
2841+
2842+ return NULL;
2843+}
2844+
2845+static int transcode_init(void)
24862846 {
24872847 int ret = 0, i, j, k;
24882848 AVFormatContext *oc;
@@ -2494,15 +2854,15 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, · 5 unmodified lines
24942854
24952855 /* init framerate emulation */
24962856 for (i = 0; i < nb_input_files; i++) {
2497− InputFile *ifile = &input_files[i];
2857+ InputFile *ifile = input_files[i];
24982858 if (ifile->rate_emu)
24992859 for (j = 0; j < ifile->nb_streams; j++)
2500− input_streams[j + ifile->ist_index].start = av_gettime();
2860+ input_streams[j + ifile->ist_index]->start = av_gettime();
25012861 }
25022862
25032863 /* output stream init */
25042864 for (i = 0; i < nb_output_files; i++) {
2505− oc = output_files[i].ctx;
2865+ oc = output_files[i]->ctx;
25062866 if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) {
25072867 av_dump_format(oc, i, oc->filename, 1);
25082868 av_log(NULL, AV_LOG_ERROR, "Output file #%d does not contain any stream\n", i);
@@ -2510,21 +2870,29 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, · 1 unmodified line
25102870 }
25112871 }
25122872
2873+ /* init complex filtergraphs */
2874+ for (i = 0; i < nb_filtergraphs; i++)
2875+ if ((ret = avfilter_graph_config(filtergraphs[i]->graph, NULL)) < 0)
2876+ return ret;
2877+
25132878 /* for each output stream, we compute the right encoding parameters */
25142879 for (i = 0; i < nb_output_streams; i++) {
2515− ost = &output_streams[i];
2516− oc = output_files[ost->file_index].ctx;
2517− ist = &input_streams[ost->source_index];
2880+ ost = output_streams[i];
2881+ oc = output_files[ost->file_index]->ctx;
2882+ ist = get_input_stream(ost);
25182883
25192884 if (ost->attachment_filename)
25202885 continue;
25212886
25222887 codec = ost->st->codec;
2523− icodec = ist->st->codec;
25242888
2525− ost->st->disposition = ist->st->disposition;
2526− codec->bits_per_raw_sample = icodec->bits_per_raw_sample;
2527− codec->chroma_sample_location = icodec->chroma_sample_location;
2889+ if (ist) {
2890+ icodec = ist->st->codec;
2891+
2892+ ost->st->disposition = ist->st->disposition;
2893+ codec->bits_per_raw_sample = icodec->bits_per_raw_sample;
2894+ codec->chroma_sample_location = icodec->chroma_sample_location;
2895+ }
25282896
25292897 if (ost->stream_copy) {
25302898 uint64_t extra_size = (uint64_t)icodec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE;
@@ -2625,7 +2993,8 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, · 94 unmodified lines
26252993 if (!ost->enc)
26262994 ost->enc = avcodec_find_encoder(codec->codec_id);
26272995
2628− ist->decoding_needed = 1;
2996+ if (ist)
2997+ ist->decoding_needed = 1;
26292998 ost->encoding_needed = 1;
26302999
26313000 switch (codec->codec_type) {
@@ -2675,32 +3044,16 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, · 43 unmodified lines
26753044 ost->resample_channels = icodec->channels;
26763045 break;
26773046 case AVMEDIA_TYPE_VIDEO:
2678− if (codec->pix_fmt == PIX_FMT_NONE)
2679− codec->pix_fmt = icodec->pix_fmt;
2680− choose_pixel_fmt(ost->st, ost->enc);
2681−
2682− if (ost->st->codec->pix_fmt == PIX_FMT_NONE) {
2683− av_log(NULL, AV_LOG_FATAL, "Video pixel format is unknown, stream cannot be encoded\n");
2684− exit_program(1);
2685− }
2686−
2687− if (!codec->width || !codec->height) {
2688− codec->width = icodec->width;
2689− codec->height = icodec->height;
2690− }
2691−
2692− ost->video_resample = codec->width != icodec->width ||
2693− codec->height != icodec->height ||
2694− codec->pix_fmt != icodec->pix_fmt;
2695− if (ost->video_resample) {
2696− codec->bits_per_raw_sample = frame_bits_per_raw_sample;
3047+ if (!ost->filter) {
3048+ FilterGraph *fg;
3049+ fg = init_simple_filtergraph(ist, ost);
3050+ if (configure_video_filters(fg)) {
3051+ av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
3052+ exit(1);
3053+ }
26973054 }
26983055
2699− ost->resample_height = icodec->height;
2700− ost->resample_width = icodec->width;
2701− ost->resample_pix_fmt = icodec->pix_fmt;
2702−
2703− if (!ost->frame_rate.num)
3056+ if (ist && !ost->frame_rate.num)
27043057 ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational) { 25, 1 };
27053058 if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) {
27063059 int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates);
@@ -2717,10 +3070,20 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, · 10 unmodified lines
27173070 AV_TIME_BASE_Q,
27183071 codec->time_base);
27193072
2720− if (configure_video_filters(ist, ost)) {
2721− av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
2722− exit_program(1);
3073+ codec->width = ost->filter->filter->inputs[0]->w;
3074+ codec->height = ost->filter->filter->inputs[0]->h;
3075+ codec->sample_aspect_ratio = ost->st->sample_aspect_ratio =
3076+ ost->frame_aspect_ratio ? // overridden by the -aspect cli option
3077+ av_d2q(ost->frame_aspect_ratio * codec->height/codec->width, 255) :
3078+ ost->filter->filter->inputs[0]->sample_aspect_ratio;
3079+ codec->pix_fmt = ost->filter->filter->inputs[0]->format;
3080+
3081+ if (codec->width != icodec->width ||
3082+ codec->height != icodec->height ||
3083+ codec->pix_fmt != icodec->pix_fmt) {
3084+ codec->bits_per_raw_sample = frame_bits_per_raw_sample;
27233085 }
3086+
27243087 break;
27253088 case AVMEDIA_TYPE_SUBTITLE:
27263089 codec->time_base = (AVRational){1, 1000};
@@ -2766,17 +3129,20 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, · 39 unmodified lines
27663129
27673130 /* open each encoder */
27683131 for (i = 0; i < nb_output_streams; i++) {
2769− ost = &output_streams[i];
3132+ ost = output_streams[i];
27703133 if (ost->encoding_needed) {
27713134 AVCodec *codec = ost->enc;
2772− AVCodecContext *dec = input_streams[ost->source_index].st->codec;
3135+ AVCodecContext *dec = NULL;
27733136 if (!codec) {
27743137 snprintf(error, sizeof(error), "Encoder (codec %s) not found for output stream #%d:%d",
27753138 avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index);
27763139 ret = AVERROR(EINVAL);
27773140 goto dump_format;
27783141 }
2779− if (dec->subtitle_header) {
3142+
3143+ if ((ist = get_input_stream(ost)))
3144+ dec = ist->st->codec;
3145+ if (dec && dec->subtitle_header) {
27803146 ost->st->codec->subtitle_header = av_malloc(dec->subtitle_header_size);
27813147 if (!ost->st->codec->subtitle_header) {
27823148 ret = AVERROR(ENOMEM);
@@ -2801,24 +3167,24 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, · 18 unmodified lines
28013167 extra_size += ost->st->codec->extradata_size;
28023168
28033169 if (ost->st->codec->me_threshold)
2804− input_streams[ost->source_index].st->codec->debug |= FF_DEBUG_MV;
3170+ input_streams[ost->source_index]->st->codec->debug |= FF_DEBUG_MV;
28053171 }
28063172 }
28073173
28083174 /* init input streams */
28093175 for (i = 0; i < nb_input_streams; i++)
2810− if ((ret = init_input_stream(i, output_streams, nb_output_streams, error, sizeof(error))) < 0)
3176+ if ((ret = init_input_stream(i, error, sizeof(error))) < 0)
28113177 goto dump_format;
28123178
28133179 /* discard unused programs */
28143180 for (i = 0; i < nb_input_files; i++) {
2815− InputFile *ifile = &input_files[i];
3181+ InputFile *ifile = input_files[i];
28163182 for (j = 0; j < ifile->ctx->nb_programs; j++) {
28173183 AVProgram *p = ifile->ctx->programs[j];
28183184 int discard = AVDISCARD_ALL;
28193185
28203186 for (k = 0; k < p->nb_stream_indexes; k++)
2821− if (!input_streams[ifile->ist_index + p->stream_index[k]].discard) {
3187+ if (!input_streams[ifile->ist_index + p->stream_index[k]]->discard) {
28223188 discard = AVDISCARD_DEFAULT;
28233189 break;
28243190 }
@@ -2828,14 +3194,14 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, · 3 unmodified lines
28283194
28293195 /* open files and write file headers */
28303196 for (i = 0; i < nb_output_files; i++) {
2831− oc = output_files[i].ctx;
3197+ oc = output_files[i]->ctx;
28323198 oc->interrupt_callback = int_cb;
2833− if (avformat_write_header(oc, &output_files[i].opts) < 0) {
3199+ if (avformat_write_header(oc, &output_files[i]->opts) < 0) {
28343200 snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?)", i);
28353201 ret = AVERROR(EINVAL);
28363202 goto dump_format;
28373203 }
2838−// assert_avoptions(output_files[i].opts);
3204+// assert_avoptions(output_files[i]->opts);
28393205 if (strcmp(oc->oformat->name, "rtp")) {
28403206 want_sdp = 0;
28413207 }
@@ -2845,13 +3211,31 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, · 3 unmodified lines
28453211 /* dump the file output parameters - cannot be done before in case
28463212 of stream copy */
28473213 for (i = 0; i < nb_output_files; i++) {
2848− av_dump_format(output_files[i].ctx, i, output_files[i].ctx->filename, 1);
3214+ av_dump_format(output_files[i]->ctx, i, output_files[i]->ctx->filename, 1);
28493215 }
28503216
28513217 /* dump the stream mapping */
28523218 av_log(NULL, AV_LOG_INFO, "Stream mapping:\n");
3219+ for (i = 0; i < nb_input_streams; i++) {
3220+ ist = input_streams[i];
3221+
3222+ for (j = 0; j < ist->nb_filters; j++) {
3223+ AVFilterLink *link = ist->filters[j]->filter->outputs[0];
3224+ if (ist->filters[j]->graph->graph_desc) {
3225+ av_log(NULL, AV_LOG_INFO, " Stream #%d:%d (%s) -> %s",
3226+ ist->file_index, ist->st->index, ist->dec ? ist->dec->name : "?",
3227+ link->dst->filter->name);
3228+ if (link->dst->input_count > 1)
3229+ av_log(NULL, AV_LOG_INFO, ":%s", link->dstpad->name);
3230+ if (nb_filtergraphs > 1)
3231+ av_log(NULL, AV_LOG_INFO, " (graph %d)", ist->filters[j]->graph->index);
3232+ av_log(NULL, AV_LOG_INFO, "\n");
3233+ }
3234+ }
3235+ }
3236+
28533237 for (i = 0; i < nb_output_streams; i++) {
2854− ost = &output_streams[i];
3238+ ost = output_streams[i];
28553239
28563240 if (ost->attachment_filename) {
28573241 /* an attached file */
@@ -2859,9 +3243,24 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, · 1 unmodified line
28593243 ost->attachment_filename, ost->file_index, ost->index);
28603244 continue;
28613245 }
3246+
3247+ if (ost->filter && ost->filter->graph->graph_desc) {
3248+ /* output from a complex graph */
3249+ AVFilterLink *link = ost->filter->filter->inputs[0];
3250+ av_log(NULL, AV_LOG_INFO, " %s", link->src->filter->name);
3251+ if (link->src->output_count > 1)
3252+ av_log(NULL, AV_LOG_INFO, ":%s", link->srcpad->name);
3253+ if (nb_filtergraphs > 1)
3254+ av_log(NULL, AV_LOG_INFO, " (graph %d)", ost->filter->graph->index);
3255+
3256+ av_log(NULL, AV_LOG_INFO, " -> Stream #%d:%d (%s)\n", ost->file_index,
3257+ ost->index, ost->enc ? ost->enc->name : "?");
3258+ continue;
3259+ }
3260+
28623261 av_log(NULL, AV_LOG_INFO, " Stream #%d:%d -> #%d:%d",
2863− input_streams[ost->source_index].file_index,
2864− input_streams[ost->source_index].st->index,
3262+ input_streams[ost->source_index]->file_index,
3263+ input_streams[ost->source_index]->st->index,
28653264 ost->file_index,
28663265 ost->index);
28673266 if (ost->audio_channels_mapped) {
@@ -2873,15 +3272,15 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, · 5 unmodified lines
28733272 av_log(NULL, AV_LOG_INFO, " %d", ost->audio_channels_map[j]);
28743273 av_log(NULL, AV_LOG_INFO, "]");
28753274 }
2876− if (ost->sync_ist != &input_streams[ost->source_index])
3275+ if (ost->sync_ist != input_streams[ost->source_index])
28773276 av_log(NULL, AV_LOG_INFO, " [sync #%d:%d]",
28783277 ost->sync_ist->file_index,
28793278 ost->sync_ist->st->index);
28803279 if (ost->stream_copy)
28813280 av_log(NULL, AV_LOG_INFO, " (copy)");
28823281 else
2883− av_log(NULL, AV_LOG_INFO, " (%s -> %s)", input_streams[ost->source_index].dec ?
2884− input_streams[ost->source_index].dec->name : "?",
3282+ av_log(NULL, AV_LOG_INFO, " (%s -> %s)", input_streams[ost->source_index]->dec ?
3283+ input_streams[ost->source_index]->dec->name : "?",
28853284 ost->enc ? ost->enc->name : "?");
28863285 av_log(NULL, AV_LOG_INFO, "\n");
28873286 }
@@ -2892,7 +3291,7 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, · 4 unmodified lines
28923291 }
28933292
28943293 if (want_sdp) {
2895− print_sdp(output_files, nb_output_files);
3294+ print_sdp();
28963295 }
28973296
28983297 return 0;
@@ -2901,8 +3300,7 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, · 2 unmodified lines
29013300 /*
29023301 * The following code is the main loop of the file converter
29033302 */
2904−static int transcode(OutputFile *output_files, int nb_output_files,
2905− InputFile *input_files, int nb_input_files)
3303+static int transcode(void)
29063304 {
29073305 int ret, i;
29083306 AVFormatContext *is, *os;
@@ -2916,7 +3314,7 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 7 unmodified lines
29163314 if (!(no_packet = av_mallocz(nb_input_files)))
29173315 exit_program(1);
29183316
2919− ret = transcode_init(output_files, nb_output_files, input_files, nb_input_files);
3317+ ret = transcode_init();
29203318 if (ret < 0)
29213319 goto fail;
29223320
@@ -2927,14 +3325,12 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 4 unmodified lines
29273325 timer_start = av_gettime();
29283326
29293327 for (; received_sigterm == 0;) {
2930− int file_index, ist_index;
3328+ int file_index, ist_index, past_recording_time = 1;
29313329 AVPacket pkt;
29323330 int64_t ipts_min;
2933− double opts_min;
29343331 int64_t cur_time= av_gettime();
29353332
29363333 ipts_min = INT64_MAX;
2937− opts_min = 1e100;
29383334 /* if 'q' pressed, exits */
29393335 if (!using_stdin) {
29403336 static int64_t last_time;
@@ -2974,15 +3370,15 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 33 unmodified lines
29743370 (n = sscanf(buf, "%63[^ ] %lf %255[^ ] %255[^\n]", target, &time, command, arg)) >= 3) {
29753371 av_log(NULL, AV_LOG_DEBUG, "Processing command target:%s time:%f command:%s arg:%s",
29763372 target, time, command, arg);
2977− for (i = 0; i < nb_output_streams; i++) {
2978− ost = &output_streams[i];
2979− if (ost->graph) {
3373+ for (i = 0; i < nb_filtergraphs; i++) {
3374+ FilterGraph *fg = filtergraphs[i];
3375+ if (fg->graph) {
29803376 if (time < 0) {
2981− ret = avfilter_graph_send_command(ost->graph, target, command, arg, buf, sizeof(buf),
3377+ ret = avfilter_graph_send_command(fg->graph, target, command, arg, buf, sizeof(buf),
29823378 key == 'c' ? AVFILTER_CMD_FLAG_ONE : 0);
29833379 fprintf(stderr, "Command reply for stream %d: ret:%d res:%s\n", i, ret, buf);
29843380 } else {
2985− ret = avfilter_graph_queue_command(ost->graph, target, command, arg, 0, time);
3381+ ret = avfilter_graph_queue_command(fg->graph, target, command, arg, 0, time);
29863382 }
29873383 }
29883384 }
@@ -2995,7 +3391,7 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 6 unmodified lines
29953391 if (key == 'd' || key == 'D'){
29963392 int debug=0;
29973393 if(key == 'D') {
2998− debug = input_streams[0].st->codec->debug<<1;
3394+ debug = input_streams[0]->st->codec->debug<<1;
29993395 if(!debug) debug = 1;
30003396 while(debug & (FF_DEBUG_DCT_COEFF|FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) //unsupported, would just crash
30013397 debug += debug;
@@ -3003,10 +3399,10 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 1 unmodified line
30033399 if(scanf("%d", &debug)!=1)
30043400 fprintf(stderr,"error parsing debug value\n");
30053401 for(i=0;i<nb_input_streams;i++) {
3006− input_streams[i].st->codec->debug = debug;
3402+ input_streams[i]->st->codec->debug = debug;
30073403 }
30083404 for(i=0;i<nb_output_streams;i++) {
3009− ost = &output_streams[i];
3405+ ost = output_streams[i];
30103406 ost->st->codec->debug = debug;
30113407 }
30123408 if(debug) av_log_set_level(AV_LOG_DEBUG);
@@ -3026,38 +3422,40 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 13 unmodified lines
30263422 }
30273423 }
30283424
3029− /* select the stream that we must read now by looking at the
3030− smallest output pts */
3031− file_index = -1;
3425+ /* check if there's any stream where output is still needed */
30323426 for (i = 0; i < nb_output_streams; i++) {
30333427 OutputFile *of;
3034− int64_t ipts;
3035− double opts;
3036− ost = &output_streams[i];
3037− of = &output_files[ost->file_index];
3038− os = output_files[ost->file_index].ctx;
3039− ist = &input_streams[ost->source_index];
3040− if (ost->is_past_recording_time || no_packet[ist->file_index] ||
3428+ ost = output_streams[i];
3429+ of = output_files[ost->file_index];
3430+ os = output_files[ost->file_index]->ctx;
3431+ if (ost->is_past_recording_time ||
30413432 (os->pb && avio_tell(os->pb) >= of->limit_filesize))
30423433 continue;
3043− opts = ost->st->pts.val * av_q2d(ost->st->time_base);
3434+ if (ost->frame_number > ost->max_frames) {
3435+ int j;
3436+ for (j = 0; j < of->ctx->nb_streams; j++)
3437+ output_streams[of->ost_index + j]->is_past_recording_time = 1;
3438+ continue;
3439+ }
3440+ past_recording_time = 0;
3441+ }
3442+ if (past_recording_time)
3443+ break;
3444+
3445+ /* select the stream that we must read now by looking at the
3446+ smallest output pts */
3447+ file_index = -1;
3448+ for (i = 0; i < nb_input_streams; i++) {
3449+ int64_t ipts;
3450+ ist = input_streams[i];
30443451 ipts = ist->pts;
3045− if (!input_files[ist->file_index].eof_reached) {
3452+ if (ist->discard || no_packet[ist->file_index])
3453+ continue;
3454+ if (!input_files[ist->file_index]->eof_reached) {
30463455 if (ipts < ipts_min) {
30473456 ipts_min = ipts;
3048− if (input_sync)
3049− file_index = ist->file_index;
3457+ file_index = ist->file_index;
30503458 }
3051− if (opts < opts_min) {
3052− opts_min = opts;
3053− if (!input_sync) file_index = ist->file_index;
3054− }
3055− }
3056− if (ost->frame_number >= ost->max_frames) {
3057− int j;
3058− for (j = 0; j < of->ctx->nb_streams; j++)
3059− output_streams[of->ost_index + j].is_past_recording_time = 1;
3060− continue;
30613459 }
30623460 }
30633461 /* if none, if is finished */
@@ -3072,7 +3470,7 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 8 unmodified lines
30723470 }
30733471
30743472 /* read a frame from it and output it in the fifo */
3075− is = input_files[file_index].ctx;
3473+ is = input_files[file_index]->ctx;
30763474 ret = av_read_frame(is, &pkt);
30773475 if (ret == AVERROR(EAGAIN)) {
30783476 no_packet[file_index] = 1;
@@ -3080,7 +3478,7 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 1 unmodified line
30803478 continue;
30813479 }
30823480 if (ret < 0) {
3083− input_files[file_index].eof_reached = 1;
3481+ input_files[file_index]->eof_reached = 1;
30843482 if (opt_shortest)
30853483 break;
30863484 else
@@ -3096,17 +3494,17 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 9 unmodified lines
30963494 }
30973495 /* the following test is needed in case new streams appear
30983496 dynamically in stream : we ignore them */
3099− if (pkt.stream_index >= input_files[file_index].nb_streams)
3497+ if (pkt.stream_index >= input_files[file_index]->nb_streams)
31003498 goto discard_packet;
3101− ist_index = input_files[file_index].ist_index + pkt.stream_index;
3102− ist = &input_streams[ist_index];
3499+ ist_index = input_files[file_index]->ist_index + pkt.stream_index;
3500+ ist = input_streams[ist_index];
31033501 if (ist->discard)
31043502 goto discard_packet;
31053503
31063504 if (pkt.dts != AV_NOPTS_VALUE)
3107− pkt.dts += av_rescale_q(input_files[ist->file_index].ts_offset, AV_TIME_BASE_Q, ist->st->time_base);
3505+ pkt.dts += av_rescale_q(input_files[ist->file_index]->ts_offset, AV_TIME_BASE_Q, ist->st->time_base);
31083506 if (pkt.pts != AV_NOPTS_VALUE)
3109− pkt.pts += av_rescale_q(input_files[ist->file_index].ts_offset, AV_TIME_BASE_Q, ist->st->time_base);
3507+ pkt.pts += av_rescale_q(input_files[ist->file_index]->ts_offset, AV_TIME_BASE_Q, ist->st->time_base);
31103508
31113509 if (pkt.pts != AV_NOPTS_VALUE)
31123510 pkt.pts *= ist->ts_scale;
@@ -3120,7 +3518,7 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 7 unmodified lines
31203518 av_ts2str(ist->next_pts), av_ts2timestr(ist->next_pts, &ist->st->time_base),
31213519 av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base),
31223520 av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base),
3123− input_files[ist->file_index].ts_offset);
3521+ input_files[ist->file_index]->ts_offset);
31243522 }
31253523
31263524 if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && !copy_ts) {
@@ -3131,10 +3529,10 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 4 unmodified lines
31313529 (delta > 1LL*dts_delta_threshold*AV_TIME_BASE &&
31323530 ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) ||
31333531 pkt_dts+1<ist->pts){
3134− input_files[ist->file_index].ts_offset -= delta;
3532+ input_files[ist->file_index]->ts_offset -= delta;
31353533 av_log(NULL, AV_LOG_DEBUG,
31363534 "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n",
3137− delta, input_files[ist->file_index].ts_offset);
3535+ delta, input_files[ist->file_index]->ts_offset);
31383536 pkt.dts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
31393537 if (pkt.pts != AV_NOPTS_VALUE)
31403538 pkt.pts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
@@ -3160,8 +3558,7 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 19 unmodified lines
31603558 }
31613559
31623560 // fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size);
3163− if (output_packet(ist, output_streams, nb_output_streams, &pkt) < 0) {
3164−
3561+ if (output_packet(ist, &pkt) < 0 || poll_filters() < 0) {
31653562 av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d\n",
31663563 ist->file_index, ist->st->index);
31673564 if (exit_on_error)
@@ -3174,42 +3571,42 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 6 unmodified lines
31743571 av_free_packet(&pkt);
31753572
31763573 /* dump report by using the output first video and audio streams */
3177− print_report(output_files, output_streams, nb_output_streams, 0, timer_start, cur_time);
3574+ print_report(0, timer_start, cur_time);
31783575 }
31793576
31803577 /* at the end of stream, we must flush the decoder buffers */
31813578 for (i = 0; i < nb_input_streams; i++) {
3182− ist = &input_streams[i];
3579+ ist = input_streams[i];
31833580 if (ist->decoding_needed) {
3184− output_packet(ist, output_streams, nb_output_streams, NULL);
3581+ output_packet(ist, NULL);
31853582 }
31863583 }
3187− flush_encoders(output_streams, nb_output_streams);
3584+ poll_filters();
3585+ flush_encoders();
31883586
31893587 term_exit();
31903588
31913589 /* write the trailer if needed and close file */
31923590 for (i = 0; i < nb_output_files; i++) {
3193− os = output_files[i].ctx;
3591+ os = output_files[i]->ctx;
31943592 av_write_trailer(os);
31953593 }
31963594
31973595 /* dump report by using the first video and audio streams */
3198− print_report(output_files, output_streams, nb_output_streams, 1, timer_start, av_gettime());
3596+ print_report(1, timer_start, av_gettime());
31993597
32003598 /* close each encoder */
32013599 for (i = 0; i < nb_output_streams; i++) {
3202− ost = &output_streams[i];
3600+ ost = output_streams[i];
32033601 if (ost->encoding_needed) {
32043602 av_freep(&ost->st->codec->stats_in);
32053603 avcodec_close(ost->st->codec);
32063604 }
3207− avfilter_graph_free(&ost->graph);
32083605 }
32093606
32103607 /* close each decoder */
32113608 for (i = 0; i < nb_input_streams; i++) {
3212− ist = &input_streams[i];
3609+ ist = input_streams[i];
32133610 if (ist->decoding_needed) {
32143611 avcodec_close(ist->st->codec);
32153612 }
@@ -3223,7 +3620,7 @@ static int transcode(OutputFile *output_files, int nb_output_files, · 7 unmodified lines
32233620
32243621 if (output_streams) {
32253622 for (i = 0; i < nb_output_streams; i++) {
3226− ost = &output_streams[i];
3623+ ost = output_streams[i];
32273624 if (ost) {
32283625 if (ost->stream_copy)
32293626 av_freep(&ost->st->codec->extradata);
@@ -3314,13 +3711,13 @@ static int opt_map(OptionsContext *o, const char *opt, const char *arg) · 84 unmodified lines
33143711 }
33153712 if (*sync)
33163713 sync++;
3317− for (i = 0; i < input_files[sync_file_idx].nb_streams; i++)
3318− if (check_stream_specifier(input_files[sync_file_idx].ctx,
3319− input_files[sync_file_idx].ctx->streams[i], sync) == 1) {
3714+ for (i = 0; i < input_files[sync_file_idx]->nb_streams; i++)
3715+ if (check_stream_specifier(input_files[sync_file_idx]->ctx,
3716+ input_files[sync_file_idx]->ctx->streams[i], sync) == 1) {
33203717 sync_stream_idx = i;
33213718 break;
33223719 }
3323− if (i == input_files[sync_file_idx].nb_streams) {
3720+ if (i == input_files[sync_file_idx]->nb_streams) {
33243721 av_log(NULL, AV_LOG_FATAL, "Sync stream specification in map %s does not "
33253722 "match any streams.\n", arg);
33263723 exit_program(1);
@@ -3328,6 +3725,18 @@ static int opt_map(OptionsContext *o, const char *opt, const char *arg) · 1 unmodified line
33283725 }
33293726
33303727
3728+ if (map[0] == '[') {
3729+ /* this mapping refers to lavfi output */
3730+ const char *c = map + 1;
3731+ o->stream_maps = grow_array(o->stream_maps, sizeof(*o->stream_maps),
3732+ &o->nb_stream_maps, o->nb_stream_maps + 1);
3733+ m = &o->stream_maps[o->nb_stream_maps - 1];
3734+ m->linklabel = av_get_token(&c, "]");
3735+ if (!m->linklabel) {
3736+ av_log(NULL, AV_LOG_ERROR, "Invalid output link label: %s.\n", map);
3737+ exit_program(1);
3738+ }
3739+ } else {
33313740 file_idx = strtol(map, &p, 0);
33323741 if (file_idx >= nb_input_files || file_idx < 0) {
33333742 av_log(NULL, AV_LOG_FATAL, "Invalid input file index: %d.\n", file_idx);
@@ -3338,14 +3747,14 @@ static int opt_map(OptionsContext *o, const char *opt, const char *arg) · 4 unmodified lines
33383747 for (i = 0; i < o->nb_stream_maps; i++) {
33393748 m = &o->stream_maps[i];
33403749 if (file_idx == m->file_index &&
3341− check_stream_specifier(input_files[m->file_index].ctx,
3342− input_files[m->file_index].ctx->streams[m->stream_index],
3750+ check_stream_specifier(input_files[m->file_index]->ctx,
3751+ input_files[m->file_index]->ctx->streams[m->stream_index],
33433752 *p == ':' ? p + 1 : p) > 0)
33443753 m->disabled = 1;
33453754 }
33463755 else
3347− for (i = 0; i < input_files[file_idx].nb_streams; i++) {
3348− if (check_stream_specifier(input_files[file_idx].ctx, input_files[file_idx].ctx->streams[i],
3756+ for (i = 0; i < input_files[file_idx]->nb_streams; i++) {
3757+ if (check_stream_specifier(input_files[file_idx]->ctx, input_files[file_idx]->ctx->streams[i],
33493758 *p == ':' ? p + 1 : p) <= 0)
33503759 continue;
33513760 o->stream_maps = grow_array(o->stream_maps, sizeof(*o->stream_maps),
@@ -3363,6 +3772,7 @@ static int opt_map(OptionsContext *o, const char *opt, const char *arg) · 11 unmodified lines
33633772 m->sync_stream_index = i;
33643773 }
33653774 }
3775+ }
33663776
33673777 if (!m) {
33683778 av_log(NULL, AV_LOG_FATAL, "Stream map '%s' matches no streams.\n", arg);
@@ -3422,12 +3832,12 @@ static int opt_map_channel(OptionsContext *o, const char *opt, const char *arg) · 53 unmodified lines
34223832 exit_program(1);
34233833 }
34243834 if (m->stream_idx < 0 ||
3425− m->stream_idx >= input_files[m->file_idx].nb_streams) {
3835+ m->stream_idx >= input_files[m->file_idx]->nb_streams) {
34263836 av_log(NULL, AV_LOG_FATAL, "mapchan: invalid input file stream index #%d.%d\n",
34273837 m->file_idx, m->stream_idx);
34283838 exit_program(1);
34293839 }
3430− st = input_files[m->file_idx].ctx->streams[m->stream_idx];
3840+ st = input_files[m->file_idx]->ctx->streams[m->stream_idx];
34313841 if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
34323842 av_log(NULL, AV_LOG_FATAL, "mapchan: stream #%d.%d is not an audio stream.\n",
34333843 m->file_idx, m->stream_idx);
@@ -3614,10 +4024,14 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) · 180 unmodified lines
36144024 for (i = 0; i < ic->nb_streams; i++) {
36154025 AVStream *st = ic->streams[i];
36164026 AVCodecContext *dec = st->codec;
3617− InputStream *ist;
4027+ InputStream *ist = av_mallocz(sizeof(*ist));
4028+
4029+ if (!ist)
4030+ exit_program(1);
36184031
36194032 input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1);
3620− ist = &input_streams[nb_input_streams - 1];
4033+ input_streams[nb_input_streams - 1] = ist;
4034+
36214035 ist->st = st;
36224036 ist->file_index = nb_input_files;
36234037 ist->discard = 1;
@@ -3645,6 +4059,10 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) · 21 unmodified lines
36454059 dec->flags |= CODEC_FLAG_EMU_EDGE;
36464060 }
36474061
4062+ ist->resample_height = dec->height;
4063+ ist->resample_width = dec->width;
4064+ ist->resample_pix_fmt = dec->pix_fmt;
4065+
36484066 break;
36494067 case AVMEDIA_TYPE_AUDIO:
36504068 case AVMEDIA_TYPE_DATA:
@@ -3819,11 +4237,14 @@ static int opt_input_file(OptionsContext *o, const char *opt, const char *filena · 168 unmodified lines
38194237 av_dump_format(ic, nb_input_files, filename, 0);
38204238
38214239 input_files = grow_array(input_files, sizeof(*input_files), &nb_input_files, nb_input_files + 1);
3822− input_files[nb_input_files - 1].ctx = ic;
3823− input_files[nb_input_files - 1].ist_index = nb_input_streams - ic->nb_streams;
3824− input_files[nb_input_files - 1].ts_offset = o->input_ts_offset - (copy_ts ? 0 : timestamp);
3825− input_files[nb_input_files - 1].nb_streams = ic->nb_streams;
3826− input_files[nb_input_files - 1].rate_emu = o->rate_emu;
4240+ if (!(input_files[nb_input_files - 1] = av_mallocz(sizeof(*input_files[0]))))
4241+ exit_program(1);
4242+
4243+ input_files[nb_input_files - 1]->ctx = ic;
4244+ input_files[nb_input_files - 1]->ist_index = nb_input_streams - ic->nb_streams;
4245+ input_files[nb_input_files - 1]->ts_offset = o->input_ts_offset - (copy_ts ? 0 : timestamp);
4246+ input_files[nb_input_files - 1]->nb_streams = ic->nb_streams;
4247+ input_files[nb_input_files - 1]->rate_emu = o->rate_emu;
38274248
38284249 for (i = 0; i < o->nb_dump_attachment; i++) {
38294250 int j;
@@ -3947,7 +4368,10 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e · 117 unmodified lines
39474368
39484369 output_streams = grow_array(output_streams, sizeof(*output_streams), &nb_output_streams,
39494370 nb_output_streams + 1);
3950− ost = &output_streams[nb_output_streams - 1];
4371+ if (!(ost = av_mallocz(sizeof(*ost))))
4372+ exit_program(1);
4373+ output_streams[nb_output_streams - 1] = ost;
4374+
39514375 ost->file_index = nb_output_files;
39524376 ost->index = idx;
39534377 ost->st = st;
@@ -4028,11 +4452,13 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e · 74 unmodified lines
40284452
40294453 ost->source_index = source_index;
40304454 if (source_index >= 0) {
4031− ost->sync_ist = &input_streams[source_index];
4032− input_streams[source_index].discard = 0;
4033− input_streams[source_index].st->discard = AVDISCARD_NONE;
4455+ ost->sync_ist = input_streams[source_index];
4456+ input_streams[source_index]->discard = 0;
4457+ input_streams[source_index]->st->discard = AVDISCARD_NONE;
40344458 }
40354459
4460+ ost->pix_fmts[0] = ost->pix_fmts[1] = PIX_FMT_NONE;
4461+
40364462 return ost;
40374463 }
40384464
@@ -4216,7 +4642,7 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in · 177 unmodified lines
42164642 /* check for channel mapping for this audio stream */
42174643 for (n = 0; n < o->nb_audio_channel_maps; n++) {
42184644 AudioChannelMap *map = &o->audio_channel_maps[n];
4219− InputStream *ist = &input_streams[ost->source_index];
4645+ InputStream *ist = input_streams[ost->source_index];
42204646 if ((map->channel_idx == -1 || (ist->file_index == map->file_idx && ist->st->index == map->stream_idx)) &&
42214647 (map->ofile_idx == -1 || ost->file_index == map->ofile_idx) &&
42224648 (map->ostream_idx == -1 || ost->st->index == map->ostream_idx)) {
@@ -4370,15 +4796,43 @@ static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch · 147 unmodified lines
43704796 return 0;
43714797 }
43724798
4799+static void init_output_filter(OutputFilter *ofilter, OptionsContext *o,
4800+ AVFormatContext *oc)
4801+{
4802+ OutputStream *ost;
4803+
4804+ if (ofilter->out_tmp->filter_ctx->output_pads[ofilter->out_tmp->pad_idx].type != AVMEDIA_TYPE_VIDEO) {
4805+ av_log(NULL, AV_LOG_FATAL, "Only video filters are supported currently.\n");
4806+ exit_program(1);
4807+ }
4808+
4809+ ost = new_video_stream(o, oc, -1);
4810+ ost->source_index = -1;
4811+ ost->filter = ofilter;
4812+
4813+ ofilter->ost = ost;
4814+
4815+ if (configure_output_filter(ofilter->graph, ofilter, ofilter->out_tmp) < 0) {
4816+ av_log(NULL, AV_LOG_FATAL, "Error configuring filter.\n");
4817+ exit_program(1);
4818+ }
4819+ avfilter_inout_free(&ofilter->out_tmp);
4820+}
4821+
43734822 static void opt_output_file(void *optctx, const char *filename)
43744823 {
43754824 OptionsContext *o = optctx;
43764825 AVFormatContext *oc;
4377− int i, err;
4826+ int i, j, err;
43784827 AVOutputFormat *file_oformat;
43794828 OutputStream *ost;
43804829 InputStream *ist;
43814830
4831+ if (configure_complex_filters() < 0) {
4832+ av_log(NULL, AV_LOG_FATAL, "Error configuring filters.\n");
4833+ exit_program(1);
4834+ }
4835+
43824836 if (!strcmp(filename, "-"))
43834837 filename = "pipe:";
43844838
@@ -4390,6 +4844,24 @@ static void opt_output_file(void *optctx, const char *filename) · 5 unmodified lines
43904844 file_oformat= oc->oformat;
43914845 oc->interrupt_callback = int_cb;
43924846
4847+ /* create streams for all unlabeled output pads */
4848+ for (i = 0; i < nb_filtergraphs; i++) {
4849+ FilterGraph *fg = filtergraphs[i];
4850+ for (j = 0; j < fg->nb_outputs; j++) {
4851+ OutputFilter *ofilter = fg->outputs[j];
4852+
4853+ if (!ofilter->out_tmp || ofilter->out_tmp->name)
4854+ continue;
4855+
4856+ switch (ofilter->out_tmp->filter_ctx->output_pads[ofilter->out_tmp->pad_idx].type) {
4857+ case AVMEDIA_TYPE_VIDEO: o->video_disable = 1; break;
4858+ case AVMEDIA_TYPE_AUDIO: o->audio_disable = 1; break;
4859+ case AVMEDIA_TYPE_SUBTITLE: o->subtitle_disable = 1; break;
4860+ }
4861+ init_output_filter(ofilter, o, oc);
4862+ }
4863+ }
4864+
43934865 if (!strcmp(file_oformat->name, "ffm") &&
43944866 av_strstart(filename, "http:", NULL)) {
43954867 int j;
@@ -4401,9 +4873,9 @@ static void opt_output_file(void *optctx, const char *filename) · 5 unmodified lines
44014873 exit_program(1);
44024874 }
44034875 for(j = nb_output_streams - oc->nb_streams; j < nb_output_streams; j++) {
4404− ost = &output_streams[j];
4876+ ost = output_streams[j];
44054877 for (i = 0; i < nb_input_streams; i++) {
4406− ist = &input_streams[i];
4878+ ist = input_streams[i];
44074879 if(ist->st->codec->codec_type == ost->st->codec->codec_type){
44084880 ost->sync_ist= ist;
44094881 ost->source_index= i;
@@ -4424,7 +4896,7 @@ static void opt_output_file(void *optctx, const char *filename) · 14 unmodified lines
44244896 if (!o->video_disable && oc->oformat->video_codec != CODEC_ID_NONE) {
44254897 int area = 0, idx = -1;
44264898 for (i = 0; i < nb_input_streams; i++) {
4427− ist = &input_streams[i];
4899+ ist = input_streams[i];
44284900 if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
44294901 ist->st->codec->width * ist->st->codec->height > area) {
44304902 area = ist->st->codec->width * ist->st->codec->height;
@@ -4439,7 +4911,7 @@ static void opt_output_file(void *optctx, const char *filename) · 8 unmodified lines
44394911 if (!o->audio_disable && oc->oformat->audio_codec != CODEC_ID_NONE) {
44404912 int channels = 0, idx = -1;
44414913 for (i = 0; i < nb_input_streams; i++) {
4442− ist = &input_streams[i];
4914+ ist = input_streams[i];
44434915 if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
44444916 ist->st->codec->channels > channels) {
44454917 channels = ist->st->codec->channels;
@@ -4453,7 +4925,7 @@ static void opt_output_file(void *optctx, const char *filename) · 7 unmodified lines
44534925 /* subtitles: pick first */
44544926 if (!o->subtitle_disable && (oc->oformat->subtitle_codec != CODEC_ID_NONE || subtitle_codec_name)) {
44554927 for (i = 0; i < nb_input_streams; i++)
4456− if (input_streams[i].st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
4928+ if (input_streams[i]->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
44574929 new_subtitle_stream(o, oc, i);
44584930 break;
44594931 }
@@ -4462,12 +4934,35 @@ static void opt_output_file(void *optctx, const char *filename) · 2 unmodified lines
44624934 } else {
44634935 for (i = 0; i < o->nb_stream_maps; i++) {
44644936 StreamMap *map = &o->stream_maps[i];
4465− int src_idx = input_files[map->file_index].ist_index + map->stream_index;
4937+ int src_idx = input_files[map->file_index]->ist_index + map->stream_index;
44664938
44674939 if (map->disabled)
44684940 continue;
44694941
4470− ist = &input_streams[input_files[map->file_index].ist_index + map->stream_index];
4942+ if (map->linklabel) {
4943+ FilterGraph *fg;
4944+ OutputFilter *ofilter = NULL;
4945+ int j, k;
4946+
4947+ for (j = 0; j < nb_filtergraphs; j++) {
4948+ fg = filtergraphs[j];
4949+ for (k = 0; k < fg->nb_outputs; k++) {
4950+ AVFilterInOut *out = fg->outputs[k]->out_tmp;
4951+ if (out && !strcmp(out->name, map->linklabel)) {
4952+ ofilter = fg->outputs[k];
4953+ goto loop_end;
4954+ }
4955+ }
4956+ }
4957+loop_end:
4958+ if (!ofilter) {
4959+ av_log(NULL, AV_LOG_FATAL, "Output with label '%s' does not exist "
4960+ "in any defined filter graph.\n", map->linklabel);
4961+ exit_program(1);
4962+ }
4963+ init_output_filter(ofilter, o, oc);
4964+ } else {
4965+ ist = input_streams[input_files[map->file_index]->ist_index + map->stream_index];
44714966 if(o->subtitle_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE)
44724967 continue;
44734968 if(o-> audio_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
@@ -4488,13 +4983,15 @@ static void opt_output_file(void *optctx, const char *filename) · 14 unmodified lines
44884983 map->file_index, map->stream_index);
44894984 exit_program(1);
44904985 }
4986+
4987+ }
44914988 }
44924989 }
44934990
44944991
44954992 for (i = nb_output_streams - oc->nb_streams; i < nb_output_streams; i++) { //for all streams of this output file
44964993 AVDictionaryEntry *e;
4497− ost = &output_streams[i];
4994+ ost = output_streams[i];
44984995
44994996 if ( ost->stream_copy
45004997 && (e = av_dict_get(codec_opts, "flags", NULL, AV_DICT_IGNORE_SUFFIX))
@@ -4539,14 +5036,17 @@ static void opt_output_file(void *optctx, const char *filename) · 38 unmodified lines
45395036 }
45405037
45415038 output_files = grow_array(output_files, sizeof(*output_files), &nb_output_files, nb_output_files + 1);
4542− output_files[nb_output_files - 1].ctx = oc;
4543− output_files[nb_output_files - 1].ost_index = nb_output_streams - oc->nb_streams;
4544− output_files[nb_output_files - 1].recording_time = o->recording_time;
5039+ if (!(output_files[nb_output_files - 1] = av_mallocz(sizeof(*output_files[0]))))
5040+ exit_program(1);
5041+
5042+ output_files[nb_output_files - 1]->ctx = oc;
5043+ output_files[nb_output_files - 1]->ost_index = nb_output_streams - oc->nb_streams;
5044+ output_files[nb_output_files - 1]->recording_time = o->recording_time;
45455045 if (o->recording_time != INT64_MAX)
45465046 oc->duration = o->recording_time;
4547− output_files[nb_output_files - 1].start_time = o->start_time;
4548− output_files[nb_output_files - 1].limit_filesize = o->limit_filesize;
4549− av_dict_copy(&output_files[nb_output_files - 1].opts, format_opts, 0);
5047+ output_files[nb_output_files - 1]->start_time = o->start_time;
5048+ output_files[nb_output_files - 1]->limit_filesize = o->limit_filesize;
5049+ av_dict_copy(&output_files[nb_output_files - 1]->opts, format_opts, 0);
45505050
45515051 /* check filename in case of an image number is expected */
45525052 if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
@@ -4563,7 +5063,7 @@ static void opt_output_file(void *optctx, const char *filename) · 10 unmodified lines
45635063 /* open the file */
45645064 if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE,
45655065 &oc->interrupt_callback,
4566− &output_files[nb_output_files - 1].opts)) < 0) {
5066+ &output_files[nb_output_files - 1]->opts)) < 0) {
45675067 print_error(filename, err);
45685068 exit_program(1);
45695069 }
@@ -4572,7 +5072,7 @@ static void opt_output_file(void *optctx, const char *filename) · 2 unmodified lines
45725072 if (o->mux_preload) {
45735073 uint8_t buf[64];
45745074 snprintf(buf, sizeof(buf), "%d", (int)(o->mux_preload*AV_TIME_BASE));
4575− av_dict_set(&output_files[nb_output_files - 1].opts, "preload", buf, 0);
5075+ av_dict_set(&output_files[nb_output_files - 1]->opts, "preload", buf, 0);
45765076 }
45775077 oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE);
45785078
@@ -4585,7 +5085,7 @@ static void opt_output_file(void *optctx, const char *filename) · 6 unmodified lines
45855085 av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d while processing metadata maps\n", in_file_index);
45865086 exit_program(1);
45875087 }
4588− copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc, in_file_index >= 0 ? input_files[in_file_index].ctx : NULL, o);
5088+ copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc, in_file_index >= 0 ? input_files[in_file_index]->ctx : NULL, o);
45895089 }
45905090
45915091 /* copy chapters */
@@ -4594,7 +5094,7 @@ static void opt_output_file(void *optctx, const char *filename) · 2 unmodified lines
45945094 /* copy chapters from the first input file that has them*/
45955095 o->chapters_input_file = -1;
45965096 for (i = 0; i < nb_input_files; i++)
4597− if (input_files[i].ctx->nb_chapters) {
5097+ if (input_files[i]->ctx->nb_chapters) {
45985098 o->chapters_input_file = i;
45995099 break;
46005100 }
@@ -4605,23 +5105,23 @@ static void opt_output_file(void *optctx, const char *filename) · 4 unmodified lines
46055105 }
46065106 }
46075107 if (o->chapters_input_file >= 0)
4608− copy_chapters(&input_files[o->chapters_input_file], &output_files[nb_output_files - 1],
5108+ copy_chapters(input_files[o->chapters_input_file], output_files[nb_output_files - 1],
46095109 !o->metadata_chapters_manual);
46105110
46115111 /* copy global metadata by default */
46125112 if (!o->metadata_global_manual && nb_input_files){
4613− av_dict_copy(&oc->metadata, input_files[0].ctx->metadata,
5113+ av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata,
46145114 AV_DICT_DONT_OVERWRITE);
46155115 if(o->recording_time != INT64_MAX)
46165116 av_dict_set(&oc->metadata, "duration", NULL, 0);
46175117 }
46185118 if (!o->metadata_streams_manual)
4619− for (i = output_files[nb_output_files - 1].ost_index; i < nb_output_streams; i++) {
5119+ for (i = output_files[nb_output_files - 1]->ost_index; i < nb_output_streams; i++) {
46205120 InputStream *ist;
4621− if (output_streams[i].source_index < 0) /* this is true e.g. for attached files */
5121+ if (output_streams[i]->source_index < 0) /* this is true e.g. for attached files */
46225122 continue;
4623− ist = &input_streams[output_streams[i].source_index];
4624− av_dict_copy(&output_streams[i].st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
5123+ ist = input_streams[output_streams[i]->source_index];
5124+ av_dict_copy(&output_streams[i]->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
46255125 }
46265126
46275127 /* process manually set metadata */
@@ -4764,8 +5264,8 @@ static int opt_target(OptionsContext *o, const char *opt, const char *arg) · 136 unmodified lines
47645264 if (nb_input_files) {
47655265 int i, j, fr;
47665266 for (j = 0; j < nb_input_files; j++) {
4767− for (i = 0; i < input_files[j].nb_streams; i++) {
4768− AVCodecContext *c = input_files[j].ctx->streams[i]->codec;
5267+ for (i = 0; i < input_files[j]->nb_streams; i++) {
5268+ AVCodecContext *c = input_files[j]->ctx->streams[i]->codec;
47695269 if (c->codec_type != AVMEDIA_TYPE_VIDEO)
47705270 continue;
47715271 fr = c->time_base.den * 1000 / c->time_base.num;
@@ -5080,6 +5580,17 @@ static int opt_channel_layout(OptionsContext *o, const char *opt, const char *ar · 308 unmodified lines
50805580 return ret;
50815581 }
50825582
5583+static int opt_filter_complex(const char *opt, const char *arg)
5584+{
5585+ filtergraphs = grow_array(filtergraphs, sizeof(*filtergraphs),
5586+ &nb_filtergraphs, nb_filtergraphs + 1);
5587+ if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0]))))
5588+ return AVERROR(ENOMEM);
5589+ filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1;
5590+ filtergraphs[nb_filtergraphs - 1]->graph_desc = arg;
5591+ return 0;
5592+}
5593+
50835594 #define OFFSET(x) offsetof(OptionsContext, x)
50845595 static const OptionDef options[] = {
50855596 /* main options */
@@ -5131,6 +5642,7 @@ static const OptionDef options[] = { · 45 unmodified lines
51315642 { "qscale", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_qscale}, "use fixed quality scale (VBR)", "q" },
51325643 { "profile", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_profile}, "set profile", "profile" },
51335644 { "filter", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(filters)}, "set stream filterchain", "filter_list" },
5645+ { "filter_complex", HAS_ARG | OPT_EXPERT, {(void*)opt_filter_complex}, "create a complex filtergraph", "graph_description" },
51345646 { "stats", OPT_BOOL, {&print_stats}, "print progress report during encoding", },
51355647 { "attach", HAS_ARG | OPT_FUNC2, {(void*)opt_attach}, "add an attachment to the output file", "filename" },
51365648 { "dump_attachment", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(dump_attachment)}, "extract an attachment into a file", "filename" },
@@ -5274,7 +5786,7 @@ int main(int argc, char **argv) · 137 unmodified lines
52745786 }
52755787
52765788 current_time = ti = getutime();
5277− if (transcode(output_files, nb_output_files, input_files, nb_input_files) < 0)
5789+ if (transcode() < 0)
52785790 exit_program(1);
52795791 ti = getutime() - ti;
52805792 if (do_benchmark) {
ffplay.c+1−1
@@ -1740,9 +1740,9 @@ static AVFilter input_filter = · 1739 unmodified lines
17401740
17411741 static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters)
17421742 {
1743+ static const enum PixelFormat pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
17431744 char sws_flags_str[128];
17441745 int ret;
1745− enum PixelFormat pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
17461746 AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
17471747 AVFilterContext *filt_src = NULL, *filt_out = NULL;
17481748 snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%d", sws_flags);
libavfilter/graphparser.c+1−1
@@ -242,7 +242,7 @@ static int link_filter_inouts(AVFilterContext *filt_ctx, · 241 unmodified lines
242242 } else {
243243 p->filter_ctx = filt_ctx;
244244 p->pad_idx = pad;
245− insert_inout(open_inputs, p);
245+ append_inout(open_inputs, &p);
246246 }
247247 }
248248
libavfilter/sink_buffer.c+7−3
@@ -165,9 +165,9 @@ static av_cold int vsink_init(AVFilterContext *ctx, const char *args, void *opaq · 164 unmodified lines
165165 av_unused AVBufferSinkParams *params;
166166
167167 if (!opaque) {
168− av_log(ctx, AV_LOG_ERROR,
168+ av_log(ctx, AV_LOG_WARNING,
169169 "No opaque field provided\n");
170− return AVERROR(EINVAL);
170+ buf->pixel_fmts = NULL;
171171 } else {
172172 #if FF_API_OLD_VSINK_API
173173 const int *pixel_fmts = (const enum PixelFormat *)opaque;
@@ -194,7 +194,11 @@ static int vsink_query_formats(AVFilterContext *ctx) · 20 unmodified lines
194194 {
195195 BufferSinkContext *buf = ctx->priv;
196196
197− avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(buf->pixel_fmts));
197+ if (buf->pixel_fmts)
198+ avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(buf->pixel_fmts));
199+ else
200+ avfilter_default_query_formats(ctx);
201+
198202 return 0;
199203 }
200204
tests/codec-regression.sh+3−3
@@ -73,9 +73,9 @@ do_video_encoding mpeg2threadivlc.mpg "-qscale 10 -vcodec mpeg2video -f mpeg1vid · 72 unmodified lines
7373 do_video_decoding
7474
7575 # mpeg2 encoding interlaced
76−file=${outfile}mpeg2reuse.mpg
77−do_avconv $file $DEC_OPTS -me_threshold 256 -i ${target_path}/${outfile}mpeg2thread.mpg $ENC_OPTS -same_quant -me_threshold 256 -mb_threshold 1024 -vcodec mpeg2video -f mpeg1video -bf 2 -flags +ildct+ilme -threads 4
78−do_video_decoding
76+#file=${outfile}mpeg2reuse.mpg
77+#do_avconv $file $DEC_OPTS -me_threshold 256 -i ${target_path}/${outfile}mpeg2thread.mpg $ENC_OPTS -same_quant -me_threshold 256 -mb_threshold 1024 -vcodec mpeg2video -f mpeg1video -bf 2 -flags +ildct+ilme -threads 4
78+#do_video_decoding
7979 fi
8080
8181 if [ -n "$do_msmpeg4v2" ] ; then
tests/ref/seek/mpeg2reuse_mpg+0−46
@@ -1,46 +0,0 @@
1−ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 20829
2−ret: 0 st:-1 flags:0 ts:-1.000000
3−ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 20829
4−ret: 0 st:-1 flags:1 ts: 1.894167
5−ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 337078 size: 26840
6−ret: 0 st: 0 flags:0 ts: 0.788334
7−ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 141401 size: 23537
8−ret:-1 st: 0 flags:1 ts:-0.317499
9−ret:-1 st:-1 flags:0 ts: 2.576668
10−ret: 0 st:-1 flags:1 ts: 1.470835
11−ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 232037 size: 26192
12−ret: 0 st: 0 flags:0 ts: 0.365002
13−ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 63793 size: 21295
14−ret:-1 st: 0 flags:1 ts:-0.740831
15−ret:-1 st:-1 flags:0 ts: 2.153336
16−ret: 0 st:-1 flags:1 ts: 1.047503
17−ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 141401 size: 23537
18−ret: 0 st: 0 flags:0 ts:-0.058330
19−ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 20829
20−ret: 0 st: 0 flags:1 ts: 2.835837
21−ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 337078 size: 26840
22−ret: 0 st:-1 flags:0 ts: 1.730004
23−ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 337078 size: 26840
24−ret: 0 st:-1 flags:1 ts: 0.624171
25−ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 63793 size: 21295
26−ret: 0 st: 0 flags:0 ts:-0.481662
27−ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 20829
28−ret: 0 st: 0 flags:1 ts: 2.412505
29−ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 337078 size: 26840
30−ret: 0 st:-1 flags:0 ts: 1.306672
31−ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 232037 size: 26192
32−ret: 0 st:-1 flags:1 ts: 0.200839
33−ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 20829
34−ret: 0 st: 0 flags:0 ts:-0.904994
35−ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 20829
36−ret: 0 st: 0 flags:1 ts: 1.989173
37−ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 337078 size: 26840
38−ret: 0 st:-1 flags:0 ts: 0.883340
39−ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 232037 size: 26192
40−ret:-1 st:-1 flags:1 ts:-0.222493
41−ret:-1 st: 0 flags:0 ts: 2.671674
42−ret: 0 st: 0 flags:1 ts: 1.565841
43−ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 232037 size: 26192
44−ret: 0 st:-1 flags:0 ts: 0.460008
45−ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 141401 size: 23537
46−ret:-1 st:-1 flags:1 ts:-0.645825
tests/ref/vsynth1/mpeg2thread_ilace+0−4
@@ -2,7 +2,3 @@ · 1 unmodified line
22 791773 ./tests/data/vsynth1/mpeg2threadivlc.mpg
33 d1658911ca83f5616c1d32abc40750de *./tests/data/mpeg2thread_ilace.vsynth1.out.yuv
44 stddev: 7.63 PSNR: 30.48 MAXDIFF: 110 bytes: 7603200/ 7603200
5−d119fe917dd81d1ff758b4ce684a8d9d *./tests/data/vsynth1/mpeg2reuse.mpg
6−2074636 ./tests/data/vsynth1/mpeg2reuse.mpg
7−92ced6afe8c02304943c400cce51a5f4 *./tests/data/mpeg2thread_ilace.vsynth1.out.yuv
8−stddev: 7.66 PSNR: 30.44 MAXDIFF: 111 bytes: 7603200/ 7603200
tests/ref/vsynth2/mpeg2thread_ilace+0−4
@@ -2,7 +2,3 @@ · 1 unmodified line
22 178801 ./tests/data/vsynth2/mpeg2threadivlc.mpg
33 8c6a7ed2eb73bd18fd2bb9829464100d *./tests/data/mpeg2thread_ilace.vsynth2.out.yuv
44 stddev: 4.72 PSNR: 34.65 MAXDIFF: 72 bytes: 7603200/ 7603200
5−864d6bf2982a61e510003a518be65a2d *./tests/data/vsynth2/mpeg2reuse.mpg
6−383419 ./tests/data/vsynth2/mpeg2reuse.mpg
7−bb20fa080cfd2b0a687ea7376ff4f902 *./tests/data/mpeg2thread_ilace.vsynth2.out.yuv
8−stddev: 4.73 PSNR: 34.63 MAXDIFF: 72 bytes: 7603200/ 7603200

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t