Commit 47787831 authored by Michael Niedermayer's avatar Michael Niedermayer

Merge commit '3b266da3'

* commit '3b266da3':
  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
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents dcd207c4 3b266da3
......@@ -370,6 +370,7 @@ int cmdutils_read_file(const char *filename, char **bufptr, size_t *size);
FILE *get_preset_file(char *filename, size_t filename_size,
const char *preset_name, int is_path, const char *codec_name);
/**
* Do all the necessary cleanup and abort.
* This function is implemented in the avtools, not cmdutils.
......
......@@ -224,6 +224,9 @@ codec-dependent.
@var{filter_graph} is a description of the filter graph to apply to
the stream. Use @code{-filters} to show all the available filters
(including also sources and sinks).
See also the @option{-filter_complex} option if you want to create filter graphs
with multiple inputs and/or outputs.
@item -pre[:@var{stream_specifier}] @var{preset_name} (@emph{output,per-stream})
Specify the preset for matching stream(s).
......@@ -522,7 +525,7 @@ Synchronize read on input.
@section Advanced options
@table @option
@item -map [-]@var{input_file_id}[:@var{stream_specifier}][,@var{sync_file_id}[:@var{stream_specifier}]] (@emph{output})
@item -map [-]@var{input_file_id}[:@var{stream_specifier}][,@var{sync_file_id}[:@var{stream_specifier}]] | @var{[linklabel]} (@emph{output})
Designate one or more input streams as a source for the output file. Each input
stream is identified by the input file index @var{input_file_id} and
......@@ -538,6 +541,10 @@ the source for output stream 1, etc.
A @code{-} character before the stream identifier creates a "negative" mapping.
It disables matching streams from already created mappings.
An alternative @var{[linklabel]} form will map outputs from complex filter
graphs (see the @option{-filter_complex} option) to the output file.
@var{linklabel} must correspond to a defined output link label in the graph.
For example, to map ALL streams from the first input file to output
@example
ffmpeg -i INPUT -map 0 output
......@@ -832,6 +839,44 @@ Specify Timecode for writing. @var{SEP} is ':' for non drop timecode and ';'
@example
ffmpeg -i input.mpg -timecode 01:02:03.04 -r 30000/1001 -s ntsc output.mpg
@end example
@item -filter_complex @var{filtergraph} (@emph{global})
Define a complex filter graph, i.e. one with arbitrary number of inputs and/or
outputs. For simple graphs -- those with one input and one output of the same
type -- see the @option{-filter} options. @var{filtergraph} is a description of
the filter graph, as described in @ref{Filtergraph syntax}.
Input link labels must refer to input streams using the
@code{[file_index:stream_specifier]} syntax (i.e. the same as @option{-map}
uses). If @var{stream_specifier} matches multiple streams, the first one will be
used. An unlabeled input will be connected to the first unused input stream of
the matching type.
Output link labels are referred to with @option{-map}. Unlabeled outputs are
added to the first output file.
For example, to overlay an image over video
@example
ffmpeg -i video.mkv -i image.png -filter_complex '[0:v][1:v]overlay[out]' -map
'[out]' out.mkv
@end example
Here @code{[0:v]} refers to the first video stream in the first input file,
which is linked to the first (main) input of the overlay filter. Similarly the
first video stream in the second input is linked to the second (overlay) input
of overlay.
Assuming there is only one video stream in each input file, we can omit input
labels, so the above is equivalent to
@example
ffmpeg -i video.mkv -i image.png -filter_complex 'overlay[out]' -map
'[out]' out.mkv
@end example
Furthermore we can omit the output label and the single output from the filter
graph will be added to the output file automatically, so we can simply write
@example
ffmpeg -i video.mkv -i image.png -filter_complex 'overlay' out.mkv
@end example
@end table
@section Preset files
......
......@@ -14,6 +14,7 @@ number of input and output pads of the filter.
A filter with no input pads is called a "source", a filter with no
output pads is called a "sink".
@anchor{Filtergraph syntax}
@section Filtergraph syntax
A filtergraph can be represented using a textual representation, which
......
......@@ -108,6 +108,7 @@ typedef struct StreamMap {
int stream_index;
int sync_file_index;
int sync_stream_index;
char *linklabel; /** name of an output link, for mapping lavfi outputs */
} StreamMap;
typedef struct {
......@@ -175,6 +176,33 @@ static unsigned int allocated_async_buf_size;
#define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
typedef struct InputFilter {
AVFilterContext *filter;
struct InputStream *ist;
struct FilterGraph *graph;
} InputFilter;
typedef struct OutputFilter {
AVFilterContext *filter;
struct OutputStream *ost;
struct FilterGraph *graph;
/* temporary storage until stream maps are processed */
AVFilterInOut *out_tmp;
} OutputFilter;
typedef struct FilterGraph {
int index;
const char *graph_desc;
AVFilterGraph *graph;
InputFilter **inputs;
int nb_inputs;
OutputFilter **outputs;
int nb_outputs;
} FilterGraph;
typedef struct FrameBuffer {
uint8_t *base[4];
uint8_t *data[4];
......@@ -195,7 +223,6 @@ typedef struct InputStream {
int decoding_needed; /* true if the packets must be decoded in 'raw_fifo' */
AVCodec *dec;
AVFrame *decoded_frame;
AVFrame *filtered_frame;
int64_t start; /* time when read started */
/* predicted dts of the next packet read for this stream or (when there are
......@@ -211,9 +238,18 @@ typedef struct InputStream {
int showed_multi_packet_warning;
AVDictionary *opts;
int resample_height;
int resample_width;
int resample_pix_fmt;
/* a pool of free buffers for decoded data */
FrameBuffer *buffer_pool;
int dr1;
/* decoded data from this stream goes into all those filters
* currently video only */
InputFilter **filters;
int nb_filters;
} InputStream;
typedef struct InputFile {
......@@ -242,17 +278,15 @@ typedef struct OutputStream {
AVCodec *enc;
int64_t max_frames;
AVFrame *output_frame;
AVFrame *filtered_frame;
/* video only */
int video_resample;
int resample_height;
int resample_width;
int resample_pix_fmt;
AVRational frame_rate;
int force_fps;
int top_field_first;
float frame_aspect_ratio;
float last_quality;
/* forced key frames */
int64_t *forced_kf_pts;
......@@ -272,10 +306,8 @@ typedef struct OutputStream {
SwrContext *swr;
AVFilterContext *output_video_filter;
AVFilterContext *input_video_filter;
OutputFilter *filter;
char *avfilter;
AVFilterGraph *graph;
int64_t sws_flags;
int64_t swr_dither_method;
......@@ -285,6 +317,8 @@ typedef struct OutputStream {
int stream_copy;
const char *attachment_filename;
int copy_initial_nonkeyframes;
enum PixelFormat pix_fmts[2];
} OutputStream;
......@@ -304,15 +338,18 @@ typedef struct OutputFile {
uint64_t limit_filesize; /* filesize limit expressed in bytes */
} OutputFile;
static InputStream *input_streams = NULL;
static int nb_input_streams = 0;
static InputFile *input_files = NULL;
static int nb_input_files = 0;
static InputStream **input_streams = NULL;
static int nb_input_streams = 0;
static InputFile **input_files = NULL;
static int nb_input_files = 0;
static OutputStream *output_streams = NULL;
static int nb_output_streams = 0;
static OutputFile *output_files = NULL;
static int nb_output_files = 0;
static OutputStream **output_streams = NULL;
static int nb_output_streams = 0;
static OutputFile **output_files = NULL;
static int nb_output_files = 0;
static FilterGraph **filtergraphs;
int nb_filtergraphs;
typedef struct OptionsContext {
/* input/output options */
......@@ -457,6 +494,7 @@ static void reset_options(OptionsContext *o, int is_input)
{
const OptionDef *po = options;
OptionsContext bak= *o;
int i;
/* all OPT_SPEC and OPT_STRING can be freed in generic way */
while (po->name) {
......@@ -477,6 +515,8 @@ static void reset_options(OptionsContext *o, int is_input)
po++;
}
for (i = 0; i < o->nb_stream_maps; i++)
av_freep(&o->stream_maps[i].linklabel);
av_freep(&o->stream_maps);
av_freep(&o->audio_channel_maps);
av_freep(&o->streamid_map);
......@@ -627,20 +667,64 @@ static void filter_release_buffer(AVFilterBuffer *fb)
unref_buffer(buf->ist, buf);
}
static int configure_video_filters(InputStream *ist, OutputStream *ost)
static void choose_pixel_fmt(AVStream *st, AVCodec *codec)
{
if (codec && codec->pix_fmts) {
const enum PixelFormat *p = codec->pix_fmts;
int has_alpha= av_pix_fmt_descriptors[st->codec->pix_fmt].nb_components % 2 == 0;
enum PixelFormat best= PIX_FMT_NONE;
if (st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
if (st->codec->codec_id == CODEC_ID_MJPEG) {
p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_NONE };
} else if (st->codec->codec_id == CODEC_ID_LJPEG) {
p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ444P, PIX_FMT_YUV420P,
PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_BGRA, PIX_FMT_NONE };
}
}
for (; *p != PIX_FMT_NONE; p++) {
best= avcodec_find_best_pix_fmt2(best, *p, st->codec->pix_fmt, has_alpha, NULL);
if (*p == st->codec->pix_fmt)
break;
}
if (*p == PIX_FMT_NONE) {
if (st->codec->pix_fmt != PIX_FMT_NONE)
av_log(NULL, AV_LOG_WARNING,
"Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n",
av_pix_fmt_descriptors[st->codec->pix_fmt].name,
codec->name,
av_pix_fmt_descriptors[best].name);
st->codec->pix_fmt = best;
}
}
}
static const enum PixelFormat *choose_pixel_fmts(OutputStream *ost)
{
if (ost->st->codec->pix_fmt != PIX_FMT_NONE) {
ost->pix_fmts[0] = ost->st->codec->pix_fmt;
return ost->pix_fmts;
} else if (ost->enc->pix_fmts)
return ost->enc->pix_fmts;
else
return NULL;
}
static int configure_video_filters(FilterGraph *fg)
{
InputStream *ist = fg->inputs[0]->ist;
OutputStream *ost = fg->outputs[0]->ost;
AVFilterContext *last_filter, *filter;
/** filter graph containing all filters including input & output */
AVCodecContext *codec = ost->st->codec;
AVCodecContext *icodec = ist->st->codec;
enum PixelFormat pix_fmts[] = { codec->pix_fmt, PIX_FMT_NONE };
enum PixelFormat *pix_fmts = choose_pixel_fmts(ost);
AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
AVRational sample_aspect_ratio;
char args[255];
int ret;
ost->graph = avfilter_graph_alloc();
if (!ost->graph)
avfilter_graph_free(&fg->graph);
fg->graph = avfilter_graph_alloc();
if (!fg->graph)
return AVERROR(ENOMEM);
if (ist->st->sample_aspect_ratio.num) {
......@@ -650,34 +734,35 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost)
snprintf(args, 255, "%d:%d:%d:%d:%d:%d:%d:flags=%d", ist->st->codec->width,
ist->st->codec->height, ist->st->codec->pix_fmt, 1, AV_TIME_BASE,
sample_aspect_ratio.num, sample_aspect_ratio.den, SWS_BILINEAR + ((icodec->flags&CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0));
sample_aspect_ratio.num, sample_aspect_ratio.den, SWS_BILINEAR + ((ist->st->codec->flags&CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0));
ret = avfilter_graph_create_filter(&ost->input_video_filter, avfilter_get_by_name("buffer"),
"src", args, NULL, ost->graph);
ret = avfilter_graph_create_filter(&fg->inputs[0]->filter,
avfilter_get_by_name("buffer"),
"src", args, NULL, fg->graph);
if (ret < 0)
return ret;
#if FF_API_OLD_VSINK_API
ret = avfilter_graph_create_filter(&ost->output_video_filter, avfilter_get_by_name("buffersink"),
"out", NULL, pix_fmts, ost->graph);
ret = avfilter_graph_create_filter(&fg->outputs[0]->filter, avfilter_get_by_name("buffersink"),
"out", NULL, pix_fmts, fg->graph);
#else
buffersink_params->pixel_fmts = pix_fmts;
ret = avfilter_graph_create_filter(&ost->output_video_filter, avfilter_get_by_name("buffersink"),
"out", NULL, buffersink_params, ost->graph);
ret = avfilter_graph_create_filter(&fg->outputs[0]->filter, avfilter_get_by_name("buffersink"),
"out", NULL, buffersink_params, fg->graph);
#endif
av_freep(&buffersink_params);
if (ret < 0)
return ret;
last_filter = ost->input_video_filter;
last_filter = fg->inputs[0]->filter;
if (codec->width != icodec->width || codec->height != icodec->height) {
if (codec->width || codec->height) {
snprintf(args, 255, "%d:%d:flags=0x%X",
codec->width,
codec->height,
(unsigned)ost->sws_flags);
if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
NULL, args, NULL, ost->graph)) < 0)
NULL, args, NULL, fg->graph)) < 0)
return ret;
if ((ret = avfilter_link(last_filter, 0, filter, 0)) < 0)
return ret;
......@@ -685,7 +770,7 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost)
}
snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags);
ost->graph->scale_sws_opts = av_strdup(args);
fg->graph->scale_sws_opts = av_strdup(args);
if (ost->avfilter) {
AVFilterInOut *outputs = avfilter_inout_alloc();
......@@ -697,31 +782,258 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost)
outputs->next = NULL;
inputs->name = av_strdup("out");
inputs->filter_ctx = ost->output_video_filter;
inputs->filter_ctx = fg->outputs[0]->filter;
inputs->pad_idx = 0;
inputs->next = NULL;
if ((ret = avfilter_graph_parse(ost->graph, ost->avfilter, &inputs, &outputs, NULL)) < 0)
if ((ret = avfilter_graph_parse(fg->graph, ost->avfilter, &inputs, &outputs, NULL)) < 0)
return ret;
av_freep(&ost->avfilter);
} else {
if ((ret = avfilter_link(last_filter, 0, ost->output_video_filter, 0)) < 0)
if ((ret = avfilter_link(last_filter, 0, fg->outputs[0]->filter, 0)) < 0)
return ret;
}
if ((ret = avfilter_graph_config(ost->graph, NULL)) < 0)
if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0)
return ret;
codec->width = ost->output_video_filter->inputs[0]->w;
codec->height = ost->output_video_filter->inputs[0]->h;
codec->sample_aspect_ratio = ost->st->sample_aspect_ratio =
ost->frame_aspect_ratio ? // overridden by the -aspect cli option
av_d2q(ost->frame_aspect_ratio * codec->height/codec->width, 255) :
ost->output_video_filter->inputs[0]->sample_aspect_ratio;
ost->filter = fg->outputs[0];
return 0;
}
static FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost)
{
FilterGraph *fg = av_mallocz(sizeof(*fg));
if (!fg)
exit_program(1);
fg->index = nb_filtergraphs;
fg->outputs = grow_array(fg->outputs, sizeof(*fg->outputs), &fg->nb_outputs,
fg->nb_outputs + 1);
if (!(fg->outputs[0] = av_mallocz(sizeof(*fg->outputs[0]))))
exit_program(1);
fg->outputs[0]->ost = ost;
fg->outputs[0]->graph = fg;
fg->inputs = grow_array(fg->inputs, sizeof(*fg->inputs), &fg->nb_inputs,
fg->nb_inputs + 1);
if (!(fg->inputs[0] = av_mallocz(sizeof(*fg->inputs[0]))))
exit_program(1);
fg->inputs[0]->ist = ist;
fg->inputs[0]->graph = fg;
ist->filters = grow_array(ist->filters, sizeof(*ist->filters),
&ist->nb_filters, ist->nb_filters + 1);
ist->filters[ist->nb_filters - 1] = fg->inputs[0];
filtergraphs = grow_array(filtergraphs, sizeof(*filtergraphs),
&nb_filtergraphs, nb_filtergraphs + 1);
filtergraphs[nb_filtergraphs - 1] = fg;
return fg;
}
static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
{
InputStream *ist;
enum AVMediaType type = in->filter_ctx->input_pads[in->pad_idx].type;
int i;
// TODO: support other filter types
if (type != AVMEDIA_TYPE_VIDEO) {
av_log(NULL, AV_LOG_FATAL, "Only video filters supported currently.\n");
exit_program(1);
}
if (in->name) {
AVFormatContext *s;
AVStream *st = NULL;
char *p;
int file_idx = strtol(in->name, &p, 0);
if (file_idx < 0 || file_idx > nb_input_files) {
av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtegraph description %s.\n",
file_idx, fg->graph_desc);
exit_program(1);
}
s = input_files[file_idx]->ctx;
for (i = 0; i < s->nb_streams; i++) {
if (s->streams[i]->codec->codec_type != type)
continue;
if (check_stream_specifier(s, s->streams[i], *p == ':' ? p + 1 : p) == 1) {
st = s->streams[i];
break;
}
}
if (!st) {
av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s "
"matches no streams.\n", p, fg->graph_desc);
exit_program(1);
}
ist = input_streams[input_files[file_idx]->ist_index + st->index];
} else {
/* find the first unused stream of corresponding type */
for (i = 0; i < nb_input_streams; i++) {
ist = input_streams[i];
if (ist->st->codec->codec_type == type && ist->discard)
break;
}
if (i == nb_input_streams) {
av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for "
"unlabeled input pad %d on filter %s", in->pad_idx,
in->filter_ctx->name);
exit_program(1);
}
}
ist->discard = 0;
ist->decoding_needed = 1;
ist->st->discard = AVDISCARD_NONE;
fg->inputs = grow_array(fg->inputs, sizeof(*fg->inputs),
&fg->nb_inputs, fg->nb_inputs + 1);
if (!(fg->inputs[fg->nb_inputs - 1] = av_mallocz(sizeof(*fg->inputs[0]))))
exit_program(1);
fg->inputs[fg->nb_inputs - 1]->ist = ist;
fg->inputs[fg->nb_inputs - 1]->graph = fg;
ist->filters = grow_array(ist->filters, sizeof(*ist->filters),
&ist->nb_filters, ist->nb_filters + 1);
ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1];
}
static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
{
AVCodecContext *codec = ofilter->ost->st->codec;
AVFilterContext *last_filter = out->filter_ctx;
int pad_idx = out->pad_idx;
int ret;
enum PixelFormat *pix_fmts = choose_pixel_fmts(ofilter->ost);
AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
#if FF_API_OLD_VSINK_API
ret = avfilter_graph_create_filter(&ofilter->filter, avfilter_get_by_name("buffersink"),
"out", NULL, pix_fmts, fg->graph);
#else
buffersink_params->pixel_fmts = pix_fmts;
ret = avfilter_graph_create_filter(&ofilter->filter, avfilter_get_by_name("buffersink"),
"out", NULL, buffersink_params, fg->graph);
#endif
av_freep(&buffersink_params);
if (ret < 0)
return ret;
if (codec->width || codec->height) {
char args[255];
snprintf(args, sizeof(args), "%d:%d:flags=0x%X",
codec->width,
codec->height,
(unsigned)ofilter->ost->sws_flags);
if ((ret = avfilter_graph_create_filter(&last_filter, avfilter_get_by_name("scale"),
NULL, args, NULL, fg->graph)) < 0)
return ret;
if ((ret = avfilter_link(out->filter_ctx, out->pad_idx, last_filter, 0)) < 0)
return ret;
pad_idx = 0;
}
if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
return ret;
return 0;
}
static int configure_complex_filter(FilterGraph *fg)
{
AVFilterInOut *inputs, *outputs, *cur;
int ret, i, init = !fg->graph;
avfilter_graph_free(&fg->graph);
if (!(fg->graph = avfilter_graph_alloc()))
return AVERROR(ENOMEM);
if ((ret = avfilter_graph_parse2(fg->graph, fg->graph_desc, &inputs, &outputs)) < 0)
return ret;
for (cur = inputs; init && cur; cur = cur->next)
init_input_filter(fg, cur);
for (cur = inputs, i = 0; cur; cur = cur->next, i++) {
InputFilter *ifilter = fg->inputs[i];
InputStream *ist = ifilter->ist;
AVRational sar;
char args[255];
sar = ist->st->sample_aspect_ratio.num ? ist->st->sample_aspect_ratio :
ist->st->codec->sample_aspect_ratio;
snprintf(args, sizeof(args), "%d:%d:%d:%d:%d:%d:%d", ist->st->codec->width,
ist->st->codec->height, ist->st->codec->pix_fmt, 1, AV_TIME_BASE,
sar.num, sar.den);
if ((ret = avfilter_graph_create_filter(&ifilter->filter,
avfilter_get_by_name("buffer"), cur->name,
args, NULL, fg->graph)) < 0)
return ret;
if ((ret = avfilter_link(ifilter->filter, 0,
cur->filter_ctx, cur->pad_idx)) < 0)
return ret;
}
avfilter_inout_free(&inputs);
if (!init) {
/* we already know the mappings between lavfi outputs and output streams,
* so we can finish the setup */
for (cur = outputs, i = 0; cur; cur = cur->next, i++)
configure_output_filter(fg, fg->outputs[i], cur);
avfilter_inout_free(&outputs);
if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0)
return ret;
} else {
/* wait until output mappings are processed */
for (cur = outputs; cur;) {
fg->outputs = grow_array(fg->outputs, sizeof(*fg->outputs),
&fg->nb_outputs, fg->nb_outputs + 1);
if (!(fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0]))))
exit_program(1);
fg->outputs[fg->nb_outputs - 1]->graph = fg;
fg->outputs[fg->nb_outputs - 1]->out_tmp = cur;
cur = cur->next;
fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL;
}
}
return 0;
}
static int configure_complex_filters(void)
{
int i, ret = 0;
for (i = 0; i < nb_filtergraphs; i++)
if (!filtergraphs[i]->graph &&
(ret = configure_complex_filter(filtergraphs[i])) < 0)
return ret;
return 0;
}
static int configure_filtergraph(FilterGraph *fg)
{
return fg->graph_desc ? configure_complex_filter(fg) : configure_video_filters(fg);
}
static int ist_in_filtergraph(FilterGraph *fg, InputStream *ist)
{
int i;
for (i = 0; i < fg->nb_inputs; i++)
if (fg->inputs[i]->ist == ist)
return 1;
return 0;
}
static void term_exit(void)
{
av_log(NULL, AV_LOG_QUIET, "%s", "");
......@@ -839,40 +1151,57 @@ static const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
void av_noreturn exit_program(int ret)
{
int i;
int i, j;
for (i = 0; i < nb_filtergraphs; i++) {
avfilter_graph_free(&filtergraphs[i]->graph);
for (j = 0; j < filtergraphs[i]->nb_inputs; j++)
av_freep(&filtergraphs[i]->inputs[j]);
av_freep(&filtergraphs[i]->inputs);
for (j = 0; j < filtergraphs[i]->nb_outputs; j++)
av_freep(&filtergraphs[i]->outputs[j]);
av_freep(&filtergraphs[i]->outputs);
av_freep(&filtergraphs[i]);
}
av_freep(&filtergraphs);
/* close files */
for (i = 0; i < nb_output_files; i++) {
AVFormatContext *s = output_files[i].ctx;
AVFormatContext *s = output_files[i]->ctx;
if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
avio_close(s->pb);
avformat_free_context(s);
av_dict_free(&output_files[i].opts);
av_dict_free(&output_files[i]->opts);
av_freep(&output_files[i]);
}
for (i = 0; i < nb_output_streams; i++) {
AVBitStreamFilterContext *bsfc = output_streams[i].bitstream_filters;
AVBitStreamFilterContext *bsfc = output_streams[i]->bitstream_filters;
while (bsfc) {
AVBitStreamFilterContext *next = bsfc->next;
av_bitstream_filter_close(bsfc);
bsfc = next;
}
output_streams[i].bitstream_filters = NULL;
output_streams[i]->bitstream_filters = NULL;
if (output_streams[i].output_frame) {
AVFrame *frame = output_streams[i].output_frame;
if (output_streams[i]->output_frame) {
AVFrame *frame = output_streams[i]->output_frame;
if (frame->extended_data != frame->data)
av_freep(&frame->extended_data);
av_freep(&frame);
}
av_freep(&output_streams[i]->filtered_frame);
av_freep(&output_streams[i]);
}
for (i = 0; i < nb_input_files; i++) {
avformat_close_input(&input_files[i].ctx);
avformat_close_input(&input_files[i]->ctx);
av_freep(&input_files[i]);
}
for (i = 0; i < nb_input_streams; i++) {
av_freep(&input_streams[i].decoded_frame);
av_freep(&input_streams[i].filtered_frame);
av_dict_free(&input_streams[i].opts);
free_buffer_pool(&input_streams[i]);
av_freep(&input_streams[i]->decoded_frame);
av_dict_free(&input_streams[i]->opts);
free_buffer_pool(input_streams[i]);
av_freep(&input_streams[i]->filters);
av_freep(&input_streams[i]);
}
if (vstats_file)
......@@ -981,41 +1310,10 @@ static void choose_sample_rate(AVStream *st, AVCodec *codec)
}
}
static void choose_pixel_fmt(AVStream *st, AVCodec *codec)
{
if (codec && codec->pix_fmts) {
const enum PixelFormat *p = codec->pix_fmts;
int has_alpha= av_pix_fmt_descriptors[st->codec->pix_fmt].nb_components % 2 == 0;
enum PixelFormat best= PIX_FMT_NONE;
if (st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
if (st->codec->codec_id == CODEC_ID_MJPEG) {
p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_NONE };
} else if (st->codec->codec_id == CODEC_ID_LJPEG) {
p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ444P, PIX_FMT_YUV420P,
PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_BGRA, PIX_FMT_NONE };
}
}
for (; *p != PIX_FMT_NONE; p++) {
best= avcodec_find_best_pix_fmt2(best, *p, st->codec->pix_fmt, has_alpha, NULL);
if (*p == st->codec->pix_fmt)
break;
}
if (*p == PIX_FMT_NONE) {
if (st->codec->pix_fmt != PIX_FMT_NONE)
av_log(NULL, AV_LOG_WARNING,
"Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n",
av_pix_fmt_descriptors[st->codec->pix_fmt].name,
codec->name,
av_pix_fmt_descriptors[best].name);
st->codec->pix_fmt = best;
}
}
}
static double
get_sync_ipts(const OutputStream *ost, int64_t pts)
{
OutputFile *of = &output_files[ost->file_index];
OutputFile *of = output_files[ost->file_index];
return (double)(pts - of->start_time) / AV_TIME_BASE;
}
......@@ -1518,19 +1816,21 @@ static void do_video_stats(AVFormatContext *os, OutputStream *ost,
static void do_video_out(AVFormatContext *s, OutputStream *ost,
InputStream *ist, AVFrame *in_picture)
AVFrame *in_picture, float quality)
{
int nb_frames, i, ret, format_video_sync;
AVCodecContext *enc;
double sync_ipts, delta;
double duration = 0;
int frame_size = 0;
float quality = same_quant ? in_picture->quality
: ost->st->codec->global_quality;
InputStream *ist = NULL;
if (ost->source_index >= 0)
ist = input_streams[ost->source_index];
enc = ost->st->codec;
if (ist->st->start_time != AV_NOPTS_VALUE && ist->st->first_dts != AV_NOPTS_VALUE) {
if (ist && ist->st->start_time != AV_NOPTS_VALUE && ist->st->first_dts != AV_NOPTS_VALUE) {
duration = FFMAX(av_q2d(ist->st->time_base), av_q2d(ist->st->codec->time_base));
if(ist->st->r_frame_rate.num)
duration= FFMAX(duration, 1/av_q2d(ist->st->r_frame_rate));
......@@ -1672,12 +1972,66 @@ static void do_video_out(AVFormatContext *s, OutputStream *ost,
ost->frame_number++;
}
if (vstats_filename && frame_size)
do_video_stats(output_files[ost->file_index].ctx, ost, frame_size);
do_video_stats(output_files[ost->file_index]->ctx, ost, frame_size);
}
static void print_report(OutputFile *output_files,
OutputStream *ost_table, int nb_ostreams,
int is_last_report, int64_t timer_start, int64_t cur_time)
/* check for new output on any of the filtergraphs */
static int poll_filters(void)
{
AVFilterBufferRef *picref;
AVFrame *filtered_frame = NULL;
int i, ret;
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
OutputFile *of = output_files[ost->file_index];
if (!ost->filter || ost->is_past_recording_time)
continue;
if (!ost->filtered_frame && !(ost->filtered_frame = avcodec_alloc_frame())) {
return AVERROR(ENOMEM);
} else
avcodec_get_frame_defaults(ost->filtered_frame);
filtered_frame = ost->filtered_frame;
while (avfilter_poll_frame(ost->filter->filter->inputs[0])) {
AVRational ist_pts_tb = ost->filter->filter->inputs[0]->time_base;
if ((ret = av_buffersink_get_buffer_ref(ost->filter->filter,
&picref,
0)) < 0) {
av_log(NULL, AV_LOG_WARNING, "AV Filter told us it has a frame available but failed to output one\n");
return ret;
}
filtered_frame->pts = av_rescale_q(picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
// if (ost->source_index >= 0)
// *filtered_frame= *input_streams[ost->source_index]->decoded_frame; //for me_threshold
if (of->start_time && filtered_frame->pts < of->start_time)
return 0;
switch (ost->filter->filter->inputs[0]->type) {
case AVMEDIA_TYPE_VIDEO:
avfilter_fill_frame_from_video_buffer_ref(filtered_frame, picref);
if (!ost->frame_aspect_ratio)
ost->st->codec->sample_aspect_ratio = picref->video->sample_aspect_ratio;
do_video_out(of->ctx, ost, filtered_frame,
same_quant ? ost->last_quality :
ost->st->codec->global_quality);
break;
default:
// TODO support audio/subtitle filters
av_assert0(0);
}
avfilter_unref_buffer(picref);
}
}
return 0;
}
static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time)
{
char buf[1024];
OutputStream *ost;
......@@ -1705,7 +2059,7 @@ static void print_report(OutputFile *output_files,
}
oc = output_files[0].ctx;
oc = output_files[0]->ctx;
total_size = avio_size(oc->pb);
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,
buf[0] = '\0';
vid = 0;
for (i = 0; i < nb_ostreams; i++) {
for (i = 0; i < nb_output_streams; i++) {
float q = -1;
ost = &ost_table[i];
ost = output_streams[i];
enc = ost->st->codec;
if (!ost->stream_copy && enc->coded_frame)
q = enc->coded_frame->quality / (float)FF_QP2LAMBDA;
......@@ -1811,14 +2165,14 @@ static void print_report(OutputFile *output_files,
}
}
static void flush_encoders(OutputStream *ost_table, int nb_ostreams)
static void flush_encoders(void)
{
int i, ret;
for (i = 0; i < nb_ostreams; i++) {
OutputStream *ost = &ost_table[i];
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
AVCodecContext *enc = ost->st->codec;
AVFormatContext *os = output_files[ost->file_index].ctx;
AVFormatContext *os = output_files[ost->file_index]->ctx;
int stop_encoding = 0;
if (!ost->encoding_needed)
......@@ -1899,8 +2253,8 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams)
*/
static int check_output_constraints(InputStream *ist, OutputStream *ost)
{
OutputFile *of = &output_files[ost->file_index];
int ist_index = ist - input_streams;
OutputFile *of = output_files[ost->file_index];
int ist_index = input_files[ist->file_index]->ist_index + ist->st->index;
if (ost->source_index != ist_index)
return 0;
......@@ -1920,7 +2274,7 @@ static int check_output_constraints(InputStream *ist, OutputStream *ost)
static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt)
{
OutputFile *of = &output_files[ost->file_index];
OutputFile *of = output_files[ost->file_index];
int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base);
AVPicture pict;
AVPacket opkt;
......@@ -1980,7 +2334,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p
static void rate_emu_sleep(InputStream *ist)
{
if (input_files[ist->file_index].rate_emu) {
if (input_files[ist->file_index]->rate_emu) {
int64_t pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE);
int64_t now = av_gettime() - ist->start;
if (pts > now)
......@@ -2091,11 +2445,11 @@ static int transcode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
rate_emu_sleep(ist);
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = &output_streams[i];
OutputStream *ost = output_streams[i];
if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
continue;
do_audio_out(output_files[ost->file_index].ctx, ost, ist, decoded_frame);
do_audio_out(output_files[ost->file_index]->ctx, ost, ist, decoded_frame);
}
return ret;
......@@ -2105,9 +2459,10 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
{
AVFrame *decoded_frame;
void *buffer_to_free = NULL;
int i, ret = 0;
int i, ret = 0, resample_changed;
int64_t *best_effort_timestamp;
AVRational *frame_sample_aspect;
float quality;
if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame()))
return AVERROR(ENOMEM);
......@@ -2125,6 +2480,7 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
if (ret < 0)
return ret;
quality = same_quant ? decoded_frame->quality : 0;
if (!*got_output) {
/* no picture yet */
return ret;
......@@ -2138,75 +2494,66 @@ static int transcode_video(InputStream *ist, AVPacket *pkt, int *got_output, int
pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free);
frame_sample_aspect= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "sample_aspect_ratio");
for(i=0;i<nb_output_streams;i++) {
OutputStream *ost = ost = &output_streams[i];
if(check_output_constraints(ist, ost) && ost->encoding_needed){
int changed = ist->st->codec->width != ost->input_video_filter->outputs[0]->w
|| ist->st->codec->height != ost->input_video_filter->outputs[0]->h
|| ist->st->codec->pix_fmt != ost->input_video_filter->outputs[0]->format;
if (!frame_sample_aspect->num)
*frame_sample_aspect = ist->st->sample_aspect_ratio;
decoded_frame->pts = ist->pts;
if (ist->dr1 && decoded_frame->type==FF_BUFFER_TYPE_USER && !changed) {
FrameBuffer *buf = decoded_frame->opaque;
AVFilterBufferRef *fb = avfilter_get_video_buffer_ref_from_arrays(
decoded_frame->data, decoded_frame->linesize,
AV_PERM_READ | AV_PERM_PRESERVE,
ist->st->codec->width, ist->st->codec->height,
ist->st->codec->pix_fmt);
avfilter_copy_frame_props(fb, decoded_frame);
fb->buf->priv = buf;
fb->buf->free = filter_release_buffer;
buf->refcount++;
av_buffersrc_buffer(ost->input_video_filter, fb);
} else
if((av_vsrc_buffer_add_frame(ost->input_video_filter, decoded_frame, AV_VSRC_BUF_FLAG_OVERWRITE)) < 0){
av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n");
exit_program(1);
}
}
}
rate_emu_sleep(ist);
if (ist->st->sample_aspect_ratio.num)
decoded_frame->sample_aspect_ratio = ist->st->sample_aspect_ratio;
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = &output_streams[i];
if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
continue;
while (av_buffersink_poll_frame(ost->output_video_filter)) {
AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base;
AVFrame *filtered_frame;
AVFilterBufferRef *picref;
if (av_buffersink_get_buffer_ref(ost->output_video_filter, &picref, 0) < 0){
av_log(NULL, AV_LOG_WARNING, "AV Filter told us it has a frame available but failed to output one\n");
goto cont;
}
if (!ist->filtered_frame && !(ist->filtered_frame = avcodec_alloc_frame())) {
ret = AVERROR(ENOMEM);
goto fail;
resample_changed = ist->resample_width != decoded_frame->width ||
ist->resample_height != decoded_frame->height ||
ist->resample_pix_fmt != decoded_frame->format;
if (resample_changed) {
av_log(NULL, AV_LOG_INFO,
"Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n",
ist->file_index, ist->st->index,
ist->resample_width, ist->resample_height, av_get_pix_fmt_name(ist->resample_pix_fmt),
decoded_frame->width, decoded_frame->height, av_get_pix_fmt_name(decoded_frame->format));
ist->resample_width = decoded_frame->width;
ist->resample_height = decoded_frame->height;
ist->resample_pix_fmt = decoded_frame->format;
for (i = 0; i < nb_filtergraphs; i++)
if (ist_in_filtergraph(filtergraphs[i], ist) &&
configure_filtergraph(filtergraphs[i]) < 0) {
av_log(NULL, AV_LOG_FATAL, "Error reinitializing filters!\n");
exit_program(1);
}
filtered_frame = ist->filtered_frame;
*filtered_frame= *decoded_frame; //for me_threshold
avfilter_fill_frame_from_video_buffer_ref(filtered_frame, picref);
filtered_frame->pts = av_rescale_q(picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
if (!ost->frame_aspect_ratio)
ost->st->codec->sample_aspect_ratio = picref->video->sample_aspect_ratio;
do_video_out(output_files[ost->file_index].ctx, ost, ist, filtered_frame);
cont:
avfilter_unref_buffer(picref);
}
frame_sample_aspect= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "sample_aspect_ratio");
for (i = 0; i < ist->nb_filters; i++) {
int changed = ist->st->codec->width != ist->filters[i]->filter->outputs[0]->w
|| ist->st->codec->height != ist->filters[i]->filter->outputs[0]->h
|| ist->st->codec->pix_fmt != ist->filters[i]->filter->outputs[0]->format;
// XXX what an ugly hack
if (ist->filters[i]->graph->nb_outputs == 1)
ist->filters[i]->graph->outputs[0]->ost->last_quality = quality;
if (!frame_sample_aspect->num)
*frame_sample_aspect = ist->st->sample_aspect_ratio;
if (ist->dr1 && decoded_frame->type==FF_BUFFER_TYPE_USER && !changed) {
FrameBuffer *buf = decoded_frame->opaque;
AVFilterBufferRef *fb = avfilter_get_video_buffer_ref_from_arrays(
decoded_frame->data, decoded_frame->linesize,
AV_PERM_READ | AV_PERM_PRESERVE,
ist->st->codec->width, ist->st->codec->height,
ist->st->codec->pix_fmt);
avfilter_copy_frame_props(fb, decoded_frame);
fb->buf->priv = buf;
fb->buf->free = filter_release_buffer;
buf->refcount++;
av_buffersrc_buffer(ist->filters[i]->filter, fb);
} else
if(av_vsrc_buffer_add_frame(ist->filters[i]->filter, decoded_frame,AV_VSRC_BUF_FLAG_OVERWRITE)<0) {
av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n");
exit_program(1);
}
}
fail:
av_free(buffer_to_free);
return ret;
}
......@@ -2224,12 +2571,12 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
rate_emu_sleep(ist);
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = &output_streams[i];
OutputStream *ost = output_streams[i];
if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
continue;
do_subtitle_out(output_files[ost->file_index].ctx, ost, ist, &subtitle, pkt->pts);
do_subtitle_out(output_files[ost->file_index]->ctx, ost, ist, &subtitle, pkt->pts);
}
avsubtitle_free(&subtitle);
......@@ -2237,9 +2584,7 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output)
}
/* pkt = NULL means EOF (needed to flush decoder buffers) */
static int output_packet(InputStream *ist,
OutputStream *ost_table, int nb_ostreams,
const AVPacket *pkt)
static int output_packet(InputStream *ist, const AVPacket *pkt)
{
int ret = 0, i;
int got_output;
......@@ -2356,8 +2701,8 @@ static int output_packet(InputStream *ist,
ist->pts = ist->dts;
ist->next_pts = ist->next_dts;
}
for (i = 0; pkt && i < nb_ostreams; i++) {
OutputStream *ost = &ost_table[i];
for (i = 0; pkt && i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
if (!check_output_constraints(ist, ost) || ost->encoding_needed)
continue;
......@@ -2368,18 +2713,18 @@ static int output_packet(InputStream *ist,
return 0;
}
static void print_sdp(OutputFile *output_files, int n)
static void print_sdp(void)
{
char sdp[2048];
int i;
AVFormatContext **avc = av_malloc(sizeof(*avc) * n);
AVFormatContext **avc = av_malloc(sizeof(*avc) * nb_output_files);
if (!avc)
exit_program(1);
for (i = 0; i < n; i++)
avc[i] = output_files[i].ctx;
for (i = 0; i < nb_output_files; i++)
avc[i] = output_files[i]->ctx;
av_sdp_create(avc, n, sdp, sizeof(sdp));
av_sdp_create(avc, nb_output_files, sdp, sizeof(sdp));
printf("SDP:\n%s\n", sdp);
fflush(stdout);
av_freep(&avc);
......@@ -2430,11 +2775,10 @@ static void get_default_channel_layouts(OutputStream *ost, InputStream *ist)
}
static int init_input_stream(int ist_index, OutputStream *output_streams, int nb_output_streams,
char *error, int error_len)
static int init_input_stream(int ist_index, char *error, int error_len)
{
InputStream *ist = &input_streams[ist_index];
int i;
InputStream *ist = input_streams[ist_index];
if (ist->decoding_needed) {
AVCodec *codec = ist->dec;
......@@ -2463,7 +2807,7 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb
if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
for (i = 0; i < nb_output_streams; i++) {
OutputStream *ost = &output_streams[i];
OutputStream *ost = output_streams[i];
if (ost->source_index == ist_index) {
if (!ist->st->codec->channel_layout || !ost->st->codec->channel_layout)
get_default_channel_layouts(ost, ist);
......@@ -2481,8 +2825,24 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb
return 0;
}
static int transcode_init(OutputFile *output_files, int nb_output_files,
InputFile *input_files, int nb_input_files)
static InputStream *get_input_stream(OutputStream *ost)
{
if (ost->source_index >= 0)
return input_streams[ost->source_index];
if (ost->filter) {
FilterGraph *fg = ost->filter->graph;
int i;
for (i = 0; i < fg->nb_inputs; i++)
if (fg->inputs[i]->ist->st->codec->codec_type == ost->st->codec->codec_type)
return fg->inputs[i]->ist;
}
return NULL;
}
static int transcode_init(void)
{
int ret = 0, i, j, k;
AVFormatContext *oc;
......@@ -2494,15 +2854,15 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
/* init framerate emulation */
for (i = 0; i < nb_input_files; i++) {
InputFile *ifile = &input_files[i];
InputFile *ifile = input_files[i];
if (ifile->rate_emu)
for (j = 0; j < ifile->nb_streams; j++)
input_streams[j + ifile->ist_index].start = av_gettime();
input_streams[j + ifile->ist_index]->start = av_gettime();
}
/* output stream init */
for (i = 0; i < nb_output_files; i++) {
oc = output_files[i].ctx;
oc = output_files[i]->ctx;
if (!oc->nb_streams && !(oc->oformat->flags & AVFMT_NOSTREAMS)) {
av_dump_format(oc, i, oc->filename, 1);
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,
}
}
/* init complex filtergraphs */
for (i = 0; i < nb_filtergraphs; i++)
if ((ret = avfilter_graph_config(filtergraphs[i]->graph, NULL)) < 0)
return ret;
/* for each output stream, we compute the right encoding parameters */
for (i = 0; i < nb_output_streams; i++) {
ost = &output_streams[i];
oc = output_files[ost->file_index].ctx;
ist = &input_streams[ost->source_index];
ost = output_streams[i];
oc = output_files[ost->file_index]->ctx;
ist = get_input_stream(ost);
if (ost->attachment_filename)
continue;
codec = ost->st->codec;
icodec = ist->st->codec;
ost->st->disposition = ist->st->disposition;
codec->bits_per_raw_sample = icodec->bits_per_raw_sample;
codec->chroma_sample_location = icodec->chroma_sample_location;
if (ist) {
icodec = ist->st->codec;
ost->st->disposition = ist->st->disposition;
codec->bits_per_raw_sample = icodec->bits_per_raw_sample;
codec->chroma_sample_location = icodec->chroma_sample_location;
}
if (ost->stream_copy) {
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,
if (!ost->enc)
ost->enc = avcodec_find_encoder(codec->codec_id);
ist->decoding_needed = 1;
if (ist)
ist->decoding_needed = 1;
ost->encoding_needed = 1;
switch (codec->codec_type) {
......@@ -2675,32 +3044,16 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
ost->resample_channels = icodec->channels;
break;
case AVMEDIA_TYPE_VIDEO:
if (codec->pix_fmt == PIX_FMT_NONE)
codec->pix_fmt = icodec->pix_fmt;
choose_pixel_fmt(ost->st, ost->enc);
if (ost->st->codec->pix_fmt == PIX_FMT_NONE) {
av_log(NULL, AV_LOG_FATAL, "Video pixel format is unknown, stream cannot be encoded\n");
exit_program(1);
}
if (!codec->width || !codec->height) {
codec->width = icodec->width;
codec->height = icodec->height;
}
ost->video_resample = codec->width != icodec->width ||
codec->height != icodec->height ||
codec->pix_fmt != icodec->pix_fmt;
if (ost->video_resample) {
codec->bits_per_raw_sample = frame_bits_per_raw_sample;
if (!ost->filter) {
FilterGraph *fg;
fg = init_simple_filtergraph(ist, ost);
if (configure_video_filters(fg)) {
av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
exit(1);
}
}
ost->resample_height = icodec->height;
ost->resample_width = icodec->width;
ost->resample_pix_fmt = icodec->pix_fmt;
if (!ost->frame_rate.num)
if (ist && !ost->frame_rate.num)
ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational) { 25, 1 };
if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) {
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,
AV_TIME_BASE_Q,
codec->time_base);
if (configure_video_filters(ist, ost)) {
av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
exit_program(1);
codec->width = ost->filter->filter->inputs[0]->w;
codec->height = ost->filter->filter->inputs[0]->h;
codec->sample_aspect_ratio = ost->st->sample_aspect_ratio =
ost->frame_aspect_ratio ? // overridden by the -aspect cli option
av_d2q(ost->frame_aspect_ratio * codec->height/codec->width, 255) :
ost->filter->filter->inputs[0]->sample_aspect_ratio;
codec->pix_fmt = ost->filter->filter->inputs[0]->format;
if (codec->width != icodec->width ||
codec->height != icodec->height ||
codec->pix_fmt != icodec->pix_fmt) {
codec->bits_per_raw_sample = frame_bits_per_raw_sample;
}
break;
case AVMEDIA_TYPE_SUBTITLE:
codec->time_base = (AVRational){1, 1000};
......@@ -2766,17 +3129,20 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
/* open each encoder */
for (i = 0; i < nb_output_streams; i++) {
ost = &output_streams[i];
ost = output_streams[i];
if (ost->encoding_needed) {
AVCodec *codec = ost->enc;
AVCodecContext *dec = input_streams[ost->source_index].st->codec;
AVCodecContext *dec = NULL;
if (!codec) {
snprintf(error, sizeof(error), "Encoder (codec %s) not found for output stream #%d:%d",
avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index);
ret = AVERROR(EINVAL);
goto dump_format;
}
if (dec->subtitle_header) {
if ((ist = get_input_stream(ost)))
dec = ist->st->codec;
if (dec && dec->subtitle_header) {
ost->st->codec->subtitle_header = av_malloc(dec->subtitle_header_size);
if (!ost->st->codec->subtitle_header) {
ret = AVERROR(ENOMEM);
......@@ -2801,24 +3167,24 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
extra_size += ost->st->codec->extradata_size;
if (ost->st->codec->me_threshold)
input_streams[ost->source_index].st->codec->debug |= FF_DEBUG_MV;
input_streams[ost->source_index]->st->codec->debug |= FF_DEBUG_MV;
}
}
/* init input streams */
for (i = 0; i < nb_input_streams; i++)
if ((ret = init_input_stream(i, output_streams, nb_output_streams, error, sizeof(error))) < 0)
if ((ret = init_input_stream(i, error, sizeof(error))) < 0)
goto dump_format;
/* discard unused programs */
for (i = 0; i < nb_input_files; i++) {
InputFile *ifile = &input_files[i];
InputFile *ifile = input_files[i];
for (j = 0; j < ifile->ctx->nb_programs; j++) {
AVProgram *p = ifile->ctx->programs[j];
int discard = AVDISCARD_ALL;
for (k = 0; k < p->nb_stream_indexes; k++)
if (!input_streams[ifile->ist_index + p->stream_index[k]].discard) {
if (!input_streams[ifile->ist_index + p->stream_index[k]]->discard) {
discard = AVDISCARD_DEFAULT;
break;
}
......@@ -2828,14 +3194,14 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
/* open files and write file headers */
for (i = 0; i < nb_output_files; i++) {
oc = output_files[i].ctx;
oc = output_files[i]->ctx;
oc->interrupt_callback = int_cb;
if (avformat_write_header(oc, &output_files[i].opts) < 0) {
if (avformat_write_header(oc, &output_files[i]->opts) < 0) {
snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?)", i);
ret = AVERROR(EINVAL);
goto dump_format;
}
// assert_avoptions(output_files[i].opts);
// assert_avoptions(output_files[i]->opts);
if (strcmp(oc->oformat->name, "rtp")) {
want_sdp = 0;
}
......@@ -2845,13 +3211,31 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
/* dump the file output parameters - cannot be done before in case
of stream copy */
for (i = 0; i < nb_output_files; i++) {
av_dump_format(output_files[i].ctx, i, output_files[i].ctx->filename, 1);
av_dump_format(output_files[i]->ctx, i, output_files[i]->ctx->filename, 1);
}
/* dump the stream mapping */
av_log(NULL, AV_LOG_INFO, "Stream mapping:\n");
for (i = 0; i < nb_input_streams; i++) {
ist = input_streams[i];
for (j = 0; j < ist->nb_filters; j++) {
AVFilterLink *link = ist->filters[j]->filter->outputs[0];
if (ist->filters[j]->graph->graph_desc) {
av_log(NULL, AV_LOG_INFO, " Stream #%d:%d (%s) -> %s",
ist->file_index, ist->st->index, ist->dec ? ist->dec->name : "?",
link->dst->filter->name);
if (link->dst->input_count > 1)
av_log(NULL, AV_LOG_INFO, ":%s", link->dstpad->name);
if (nb_filtergraphs > 1)
av_log(NULL, AV_LOG_INFO, " (graph %d)", ist->filters[j]->graph->index);
av_log(NULL, AV_LOG_INFO, "\n");
}
}
}
for (i = 0; i < nb_output_streams; i++) {
ost = &output_streams[i];
ost = output_streams[i];
if (ost->attachment_filename) {
/* an attached file */
......@@ -2859,9 +3243,24 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
ost->attachment_filename, ost->file_index, ost->index);
continue;
}
if (ost->filter && ost->filter->graph->graph_desc) {
/* output from a complex graph */
AVFilterLink *link = ost->filter->filter->inputs[0];
av_log(NULL, AV_LOG_INFO, " %s", link->src->filter->name);
if (link->src->output_count > 1)
av_log(NULL, AV_LOG_INFO, ":%s", link->srcpad->name);
if (nb_filtergraphs > 1)
av_log(NULL, AV_LOG_INFO, " (graph %d)", ost->filter->graph->index);
av_log(NULL, AV_LOG_INFO, " -> Stream #%d:%d (%s)\n", ost->file_index,
ost->index, ost->enc ? ost->enc->name : "?");
continue;
}
av_log(NULL, AV_LOG_INFO, " Stream #%d:%d -> #%d:%d",
input_streams[ost->source_index].file_index,
input_streams[ost->source_index].st->index,
input_streams[ost->source_index]->file_index,
input_streams[ost->source_index]->st->index,
ost->file_index,
ost->index);
if (ost->audio_channels_mapped) {
......@@ -2873,15 +3272,15 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
av_log(NULL, AV_LOG_INFO, " %d", ost->audio_channels_map[j]);
av_log(NULL, AV_LOG_INFO, "]");
}
if (ost->sync_ist != &input_streams[ost->source_index])
if (ost->sync_ist != input_streams[ost->source_index])
av_log(NULL, AV_LOG_INFO, " [sync #%d:%d]",
ost->sync_ist->file_index,
ost->sync_ist->st->index);
if (ost->stream_copy)
av_log(NULL, AV_LOG_INFO, " (copy)");
else
av_log(NULL, AV_LOG_INFO, " (%s -> %s)", input_streams[ost->source_index].dec ?
input_streams[ost->source_index].dec->name : "?",
av_log(NULL, AV_LOG_INFO, " (%s -> %s)", input_streams[ost->source_index]->dec ?
input_streams[ost->source_index]->dec->name : "?",
ost->enc ? ost->enc->name : "?");
av_log(NULL, AV_LOG_INFO, "\n");
}
......@@ -2892,7 +3291,7 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
}
if (want_sdp) {
print_sdp(output_files, nb_output_files);
print_sdp();
}
return 0;
......@@ -2901,8 +3300,7 @@ static int transcode_init(OutputFile *output_files, int nb_output_files,
/*
* The following code is the main loop of the file converter
*/
static int transcode(OutputFile *output_files, int nb_output_files,
InputFile *input_files, int nb_input_files)
static int transcode(void)
{
int ret, i;
AVFormatContext *is, *os;
......@@ -2916,7 +3314,7 @@ static int transcode(OutputFile *output_files, int nb_output_files,
if (!(no_packet = av_mallocz(nb_input_files)))
exit_program(1);
ret = transcode_init(output_files, nb_output_files, input_files, nb_input_files);
ret = transcode_init();
if (ret < 0)
goto fail;
......@@ -2927,14 +3325,12 @@ static int transcode(OutputFile *output_files, int nb_output_files,
timer_start = av_gettime();
for (; received_sigterm == 0;) {
int file_index, ist_index;
int file_index, ist_index, past_recording_time = 1;
AVPacket pkt;
int64_t ipts_min;
double opts_min;
int64_t cur_time= av_gettime();
ipts_min = INT64_MAX;
opts_min = 1e100;
/* if 'q' pressed, exits */
if (!using_stdin) {
static int64_t last_time;
......@@ -2974,15 +3370,15 @@ static int transcode(OutputFile *output_files, int nb_output_files,
(n = sscanf(buf, "%63[^ ] %lf %255[^ ] %255[^\n]", target, &time, command, arg)) >= 3) {
av_log(NULL, AV_LOG_DEBUG, "Processing command target:%s time:%f command:%s arg:%s",
target, time, command, arg);
for (i = 0; i < nb_output_streams; i++) {
ost = &output_streams[i];
if (ost->graph) {
for (i = 0; i < nb_filtergraphs; i++) {
FilterGraph *fg = filtergraphs[i];
if (fg->graph) {
if (time < 0) {
ret = avfilter_graph_send_command(ost->graph, target, command, arg, buf, sizeof(buf),
ret = avfilter_graph_send_command(fg->graph, target, command, arg, buf, sizeof(buf),
key == 'c' ? AVFILTER_CMD_FLAG_ONE : 0);
fprintf(stderr, "Command reply for stream %d: ret:%d res:%s\n", i, ret, buf);
} else {
ret = avfilter_graph_queue_command(ost->graph, target, command, arg, 0, time);
ret = avfilter_graph_queue_command(fg->graph, target, command, arg, 0, time);
}
}
}
......@@ -2995,7 +3391,7 @@ static int transcode(OutputFile *output_files, int nb_output_files,
if (key == 'd' || key == 'D'){
int debug=0;
if(key == 'D') {
debug = input_streams[0].st->codec->debug<<1;
debug = input_streams[0]->st->codec->debug<<1;
if(!debug) debug = 1;
while(debug & (FF_DEBUG_DCT_COEFF|FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) //unsupported, would just crash
debug += debug;
......@@ -3003,10 +3399,10 @@ static int transcode(OutputFile *output_files, int nb_output_files,
if(scanf("%d", &debug)!=1)
fprintf(stderr,"error parsing debug value\n");
for(i=0;i<nb_input_streams;i++) {
input_streams[i].st->codec->debug = debug;
input_streams[i]->st->codec->debug = debug;
}
for(i=0;i<nb_output_streams;i++) {
ost = &output_streams[i];
ost = output_streams[i];
ost->st->codec->debug = debug;
}
if(debug) av_log_set_level(AV_LOG_DEBUG);
......@@ -3026,38 +3422,40 @@ static int transcode(OutputFile *output_files, int nb_output_files,
}
}
/* select the stream that we must read now by looking at the
smallest output pts */
file_index = -1;
/* check if there's any stream where output is still needed */
for (i = 0; i < nb_output_streams; i++) {
OutputFile *of;
int64_t ipts;
double opts;
ost = &output_streams[i];
of = &output_files[ost->file_index];
os = output_files[ost->file_index].ctx;
ist = &input_streams[ost->source_index];
if (ost->is_past_recording_time || no_packet[ist->file_index] ||
ost = output_streams[i];
of = output_files[ost->file_index];
os = output_files[ost->file_index]->ctx;
if (ost->is_past_recording_time ||
(os->pb && avio_tell(os->pb) >= of->limit_filesize))
continue;
opts = ost->st->pts.val * av_q2d(ost->st->time_base);
if (ost->frame_number > ost->max_frames) {
int j;
for (j = 0; j < of->ctx->nb_streams; j++)
output_streams[of->ost_index + j]->is_past_recording_time = 1;
continue;
}
past_recording_time = 0;
}
if (past_recording_time)
break;
/* select the stream that we must read now by looking at the
smallest output pts */
file_index = -1;
for (i = 0; i < nb_input_streams; i++) {
int64_t ipts;
ist = input_streams[i];
ipts = ist->pts;
if (!input_files[ist->file_index].eof_reached) {
if (ist->discard || no_packet[ist->file_index])
continue;
if (!input_files[ist->file_index]->eof_reached) {
if (ipts < ipts_min) {
ipts_min = ipts;
if (input_sync)
file_index = ist->file_index;
file_index = ist->file_index;
}
if (opts < opts_min) {
opts_min = opts;
if (!input_sync) file_index = ist->file_index;
}
}
if (ost->frame_number >= ost->max_frames) {
int j;
for (j = 0; j < of->ctx->nb_streams; j++)
output_streams[of->ost_index + j].is_past_recording_time = 1;
continue;
}
}
/* if none, if is finished */
......@@ -3072,7 +3470,7 @@ static int transcode(OutputFile *output_files, int nb_output_files,
}
/* read a frame from it and output it in the fifo */
is = input_files[file_index].ctx;
is = input_files[file_index]->ctx;
ret = av_read_frame(is, &pkt);
if (ret == AVERROR(EAGAIN)) {
no_packet[file_index] = 1;
......@@ -3080,7 +3478,7 @@ static int transcode(OutputFile *output_files, int nb_output_files,
continue;
}
if (ret < 0) {
input_files[file_index].eof_reached = 1;
input_files[file_index]->eof_reached = 1;
if (opt_shortest)
break;
else
......@@ -3096,17 +3494,17 @@ static int transcode(OutputFile *output_files, int nb_output_files,
}
/* the following test is needed in case new streams appear
dynamically in stream : we ignore them */
if (pkt.stream_index >= input_files[file_index].nb_streams)
if (pkt.stream_index >= input_files[file_index]->nb_streams)
goto discard_packet;
ist_index = input_files[file_index].ist_index + pkt.stream_index;
ist = &input_streams[ist_index];
ist_index = input_files[file_index]->ist_index + pkt.stream_index;
ist = input_streams[ist_index];
if (ist->discard)
goto discard_packet;
if (pkt.dts != AV_NOPTS_VALUE)
pkt.dts += av_rescale_q(input_files[ist->file_index].ts_offset, AV_TIME_BASE_Q, ist->st->time_base);
pkt.dts += av_rescale_q(input_files[ist->file_index]->ts_offset, AV_TIME_BASE_Q, ist->st->time_base);
if (pkt.pts != AV_NOPTS_VALUE)
pkt.pts += av_rescale_q(input_files[ist->file_index].ts_offset, AV_TIME_BASE_Q, ist->st->time_base);
pkt.pts += av_rescale_q(input_files[ist->file_index]->ts_offset, AV_TIME_BASE_Q, ist->st->time_base);
if (pkt.pts != AV_NOPTS_VALUE)
pkt.pts *= ist->ts_scale;
......@@ -3120,7 +3518,7 @@ static int transcode(OutputFile *output_files, int nb_output_files,
av_ts2str(ist->next_pts), av_ts2timestr(ist->next_pts, &ist->st->time_base),
av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base),
av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base),
input_files[ist->file_index].ts_offset);
input_files[ist->file_index]->ts_offset);
}
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,
(delta > 1LL*dts_delta_threshold*AV_TIME_BASE &&
ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) ||
pkt_dts+1<ist->pts){
input_files[ist->file_index].ts_offset -= delta;
input_files[ist->file_index]->ts_offset -= delta;
av_log(NULL, AV_LOG_DEBUG,
"timestamp discontinuity %"PRId64", new offset= %"PRId64"\n",
delta, input_files[ist->file_index].ts_offset);
delta, input_files[ist->file_index]->ts_offset);
pkt.dts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
if (pkt.pts != AV_NOPTS_VALUE)
pkt.pts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
......@@ -3160,8 +3558,7 @@ static int transcode(OutputFile *output_files, int nb_output_files,
}
// fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size);
if (output_packet(ist, output_streams, nb_output_streams, &pkt) < 0) {
if (output_packet(ist, &pkt) < 0 || poll_filters() < 0) {
av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d\n",
ist->file_index, ist->st->index);
if (exit_on_error)
......@@ -3174,42 +3571,42 @@ static int transcode(OutputFile *output_files, int nb_output_files,
av_free_packet(&pkt);
/* dump report by using the output first video and audio streams */
print_report(output_files, output_streams, nb_output_streams, 0, timer_start, cur_time);
print_report(0, timer_start, cur_time);
}
/* at the end of stream, we must flush the decoder buffers */
for (i = 0; i < nb_input_streams; i++) {
ist = &input_streams[i];
ist = input_streams[i];
if (ist->decoding_needed) {
output_packet(ist, output_streams, nb_output_streams, NULL);
output_packet(ist, NULL);
}
}
flush_encoders(output_streams, nb_output_streams);
poll_filters();
flush_encoders();
term_exit();
/* write the trailer if needed and close file */
for (i = 0; i < nb_output_files; i++) {
os = output_files[i].ctx;
os = output_files[i]->ctx;
av_write_trailer(os);
}
/* dump report by using the first video and audio streams */
print_report(output_files, output_streams, nb_output_streams, 1, timer_start, av_gettime());
print_report(1, timer_start, av_gettime());
/* close each encoder */
for (i = 0; i < nb_output_streams; i++) {
ost = &output_streams[i];
ost = output_streams[i];
if (ost->encoding_needed) {
av_freep(&ost->st->codec->stats_in);
avcodec_close(ost->st->codec);
}
avfilter_graph_free(&ost->graph);
}
/* close each decoder */
for (i = 0; i < nb_input_streams; i++) {
ist = &input_streams[i];
ist = input_streams[i];
if (ist->decoding_needed) {
avcodec_close(ist->st->codec);
}
......@@ -3223,7 +3620,7 @@ static int transcode(OutputFile *output_files, int nb_output_files,
if (output_streams) {
for (i = 0; i < nb_output_streams; i++) {
ost = &output_streams[i];
ost = output_streams[i];
if (ost) {
if (ost->stream_copy)
av_freep(&ost->st->codec->extradata);
......@@ -3314,13 +3711,13 @@ static int opt_map(OptionsContext *o, const char *opt, const char *arg)
}
if (*sync)
sync++;
for (i = 0; i < input_files[sync_file_idx].nb_streams; i++)
if (check_stream_specifier(input_files[sync_file_idx].ctx,
input_files[sync_file_idx].ctx->streams[i], sync) == 1) {
for (i = 0; i < input_files[sync_file_idx]->nb_streams; i++)
if (check_stream_specifier(input_files[sync_file_idx]->ctx,
input_files[sync_file_idx]->ctx->streams[i], sync) == 1) {
sync_stream_idx = i;
break;
}
if (i == input_files[sync_file_idx].nb_streams) {
if (i == input_files[sync_file_idx]->nb_streams) {
av_log(NULL, AV_LOG_FATAL, "Sync stream specification in map %s does not "
"match any streams.\n", arg);
exit_program(1);
......@@ -3328,6 +3725,18 @@ static int opt_map(OptionsContext *o, const char *opt, const char *arg)
}
if (map[0] == '[') {
/* this mapping refers to lavfi output */
const char *c = map + 1;
o->stream_maps = grow_array(o->stream_maps, sizeof(*o->stream_maps),
&o->nb_stream_maps, o->nb_stream_maps + 1);
m = &o->stream_maps[o->nb_stream_maps - 1];
m->linklabel = av_get_token(&c, "]");
if (!m->linklabel) {
av_log(NULL, AV_LOG_ERROR, "Invalid output link label: %s.\n", map);
exit_program(1);
}
} else {
file_idx = strtol(map, &p, 0);
if (file_idx >= nb_input_files || file_idx < 0) {
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)
for (i = 0; i < o->nb_stream_maps; i++) {
m = &o->stream_maps[i];
if (file_idx == m->file_index &&
check_stream_specifier(input_files[m->file_index].ctx,
input_files[m->file_index].ctx->streams[m->stream_index],
check_stream_specifier(input_files[m->file_index]->ctx,
input_files[m->file_index]->ctx->streams[m->stream_index],
*p == ':' ? p + 1 : p) > 0)
m->disabled = 1;
}
else
for (i = 0; i < input_files[file_idx].nb_streams; i++) {
if (check_stream_specifier(input_files[file_idx].ctx, input_files[file_idx].ctx->streams[i],
for (i = 0; i < input_files[file_idx]->nb_streams; i++) {
if (check_stream_specifier(input_files[file_idx]->ctx, input_files[file_idx]->ctx->streams[i],
*p == ':' ? p + 1 : p) <= 0)
continue;
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)
m->sync_stream_index = i;
}
}
}
if (!m) {
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)
exit_program(1);
}
if (m->stream_idx < 0 ||
m->stream_idx >= input_files[m->file_idx].nb_streams) {
m->stream_idx >= input_files[m->file_idx]->nb_streams) {
av_log(NULL, AV_LOG_FATAL, "mapchan: invalid input file stream index #%d.%d\n",
m->file_idx, m->stream_idx);
exit_program(1);
}
st = input_files[m->file_idx].ctx->streams[m->stream_idx];
st = input_files[m->file_idx]->ctx->streams[m->stream_idx];
if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
av_log(NULL, AV_LOG_FATAL, "mapchan: stream #%d.%d is not an audio stream.\n",
m->file_idx, m->stream_idx);
......@@ -3614,10 +4024,14 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
for (i = 0; i < ic->nb_streams; i++) {
AVStream *st = ic->streams[i];
AVCodecContext *dec = st->codec;
InputStream *ist;
InputStream *ist = av_mallocz(sizeof(*ist));
if (!ist)
exit_program(1);
input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1);
ist = &input_streams[nb_input_streams - 1];
input_streams[nb_input_streams - 1] = ist;
ist->st = st;
ist->file_index = nb_input_files;
ist->discard = 1;
......@@ -3645,6 +4059,10 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
dec->flags |= CODEC_FLAG_EMU_EDGE;
}
ist->resample_height = dec->height;
ist->resample_width = dec->width;
ist->resample_pix_fmt = dec->pix_fmt;
break;
case AVMEDIA_TYPE_AUDIO:
case AVMEDIA_TYPE_DATA:
......@@ -3819,11 +4237,14 @@ static int opt_input_file(OptionsContext *o, const char *opt, const char *filena
av_dump_format(ic, nb_input_files, filename, 0);
input_files = grow_array(input_files, sizeof(*input_files), &nb_input_files, nb_input_files + 1);
input_files[nb_input_files - 1].ctx = ic;
input_files[nb_input_files - 1].ist_index = nb_input_streams - ic->nb_streams;
input_files[nb_input_files - 1].ts_offset = o->input_ts_offset - (copy_ts ? 0 : timestamp);
input_files[nb_input_files - 1].nb_streams = ic->nb_streams;
input_files[nb_input_files - 1].rate_emu = o->rate_emu;
if (!(input_files[nb_input_files - 1] = av_mallocz(sizeof(*input_files[0]))))
exit_program(1);
input_files[nb_input_files - 1]->ctx = ic;
input_files[nb_input_files - 1]->ist_index = nb_input_streams - ic->nb_streams;
input_files[nb_input_files - 1]->ts_offset = o->input_ts_offset - (copy_ts ? 0 : timestamp);
input_files[nb_input_files - 1]->nb_streams = ic->nb_streams;
input_files[nb_input_files - 1]->rate_emu = o->rate_emu;
for (i = 0; i < o->nb_dump_attachment; i++) {
int j;
......@@ -3947,7 +4368,10 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
output_streams = grow_array(output_streams, sizeof(*output_streams), &nb_output_streams,
nb_output_streams + 1);
ost = &output_streams[nb_output_streams - 1];
if (!(ost = av_mallocz(sizeof(*ost))))
exit_program(1);
output_streams[nb_output_streams - 1] = ost;
ost->file_index = nb_output_files;
ost->index = idx;
ost->st = st;
......@@ -4028,11 +4452,13 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
ost->source_index = source_index;
if (source_index >= 0) {
ost->sync_ist = &input_streams[source_index];
input_streams[source_index].discard = 0;
input_streams[source_index].st->discard = AVDISCARD_NONE;
ost->sync_ist = input_streams[source_index];
input_streams[source_index]->discard = 0;
input_streams[source_index]->st->discard = AVDISCARD_NONE;
}
ost->pix_fmts[0] = ost->pix_fmts[1] = PIX_FMT_NONE;
return ost;
}
......@@ -4216,7 +4642,7 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in
/* check for channel mapping for this audio stream */
for (n = 0; n < o->nb_audio_channel_maps; n++) {
AudioChannelMap *map = &o->audio_channel_maps[n];
InputStream *ist = &input_streams[ost->source_index];
InputStream *ist = input_streams[ost->source_index];
if ((map->channel_idx == -1 || (ist->file_index == map->file_idx && ist->st->index == map->stream_idx)) &&
(map->ofile_idx == -1 || ost->file_index == map->ofile_idx) &&
(map->ostream_idx == -1 || ost->st->index == map->ostream_idx)) {
......@@ -4370,15 +4796,43 @@ static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const ch
return 0;
}
static void init_output_filter(OutputFilter *ofilter, OptionsContext *o,
AVFormatContext *oc)
{
OutputStream *ost;
if (ofilter->out_tmp->filter_ctx->output_pads[ofilter->out_tmp->pad_idx].type != AVMEDIA_TYPE_VIDEO) {
av_log(NULL, AV_LOG_FATAL, "Only video filters are supported currently.\n");
exit_program(1);
}
ost = new_video_stream(o, oc, -1);
ost->source_index = -1;
ost->filter = ofilter;
ofilter->ost = ost;
if (configure_output_filter(ofilter->graph, ofilter, ofilter->out_tmp) < 0) {
av_log(NULL, AV_LOG_FATAL, "Error configuring filter.\n");
exit_program(1);
}
avfilter_inout_free(&ofilter->out_tmp);
}
static void opt_output_file(void *optctx, const char *filename)
{
OptionsContext *o = optctx;
AVFormatContext *oc;
int i, err;
int i, j, err;
AVOutputFormat *file_oformat;
OutputStream *ost;
InputStream *ist;
if (configure_complex_filters() < 0) {
av_log(NULL, AV_LOG_FATAL, "Error configuring filters.\n");
exit_program(1);
}
if (!strcmp(filename, "-"))
filename = "pipe:";
......@@ -4390,6 +4844,24 @@ static void opt_output_file(void *optctx, const char *filename)
file_oformat= oc->oformat;
oc->interrupt_callback = int_cb;
/* create streams for all unlabeled output pads */
for (i = 0; i < nb_filtergraphs; i++) {
FilterGraph *fg = filtergraphs[i];
for (j = 0; j < fg->nb_outputs; j++) {
OutputFilter *ofilter = fg->outputs[j];
if (!ofilter->out_tmp || ofilter->out_tmp->name)
continue;
switch (ofilter->out_tmp->filter_ctx->output_pads[ofilter->out_tmp->pad_idx].type) {
case AVMEDIA_TYPE_VIDEO: o->video_disable = 1; break;
case AVMEDIA_TYPE_AUDIO: o->audio_disable = 1; break;
case AVMEDIA_TYPE_SUBTITLE: o->subtitle_disable = 1; break;
}
init_output_filter(ofilter, o, oc);
}
}
if (!strcmp(file_oformat->name, "ffm") &&
av_strstart(filename, "http:", NULL)) {
int j;
......@@ -4401,9 +4873,9 @@ static void opt_output_file(void *optctx, const char *filename)
exit_program(1);
}
for(j = nb_output_streams - oc->nb_streams; j < nb_output_streams; j++) {
ost = &output_streams[j];
ost = output_streams[j];
for (i = 0; i < nb_input_streams; i++) {
ist = &input_streams[i];
ist = input_streams[i];
if(ist->st->codec->codec_type == ost->st->codec->codec_type){
ost->sync_ist= ist;
ost->source_index= i;
......@@ -4424,7 +4896,7 @@ static void opt_output_file(void *optctx, const char *filename)
if (!o->video_disable && oc->oformat->video_codec != CODEC_ID_NONE) {
int area = 0, idx = -1;
for (i = 0; i < nb_input_streams; i++) {
ist = &input_streams[i];
ist = input_streams[i];
if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
ist->st->codec->width * ist->st->codec->height > area) {
area = ist->st->codec->width * ist->st->codec->height;
......@@ -4439,7 +4911,7 @@ static void opt_output_file(void *optctx, const char *filename)
if (!o->audio_disable && oc->oformat->audio_codec != CODEC_ID_NONE) {
int channels = 0, idx = -1;
for (i = 0; i < nb_input_streams; i++) {
ist = &input_streams[i];
ist = input_streams[i];
if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
ist->st->codec->channels > channels) {
channels = ist->st->codec->channels;
......@@ -4453,7 +4925,7 @@ static void opt_output_file(void *optctx, const char *filename)
/* subtitles: pick first */
if (!o->subtitle_disable && (oc->oformat->subtitle_codec != CODEC_ID_NONE || subtitle_codec_name)) {
for (i = 0; i < nb_input_streams; i++)
if (input_streams[i].st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
if (input_streams[i]->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
new_subtitle_stream(o, oc, i);
break;
}
......@@ -4462,12 +4934,35 @@ static void opt_output_file(void *optctx, const char *filename)
} else {
for (i = 0; i < o->nb_stream_maps; i++) {
StreamMap *map = &o->stream_maps[i];
int src_idx = input_files[map->file_index].ist_index + map->stream_index;
int src_idx = input_files[map->file_index]->ist_index + map->stream_index;
if (map->disabled)
continue;
ist = &input_streams[input_files[map->file_index].ist_index + map->stream_index];
if (map->linklabel) {
FilterGraph *fg;
OutputFilter *ofilter = NULL;
int j, k;
for (j = 0; j < nb_filtergraphs; j++) {
fg = filtergraphs[j];
for (k = 0; k < fg->nb_outputs; k++) {
AVFilterInOut *out = fg->outputs[k]->out_tmp;
if (out && !strcmp(out->name, map->linklabel)) {
ofilter = fg->outputs[k];
goto loop_end;
}
}
}
loop_end:
if (!ofilter) {
av_log(NULL, AV_LOG_FATAL, "Output with label '%s' does not exist "
"in any defined filter graph.\n", map->linklabel);
exit_program(1);
}
init_output_filter(ofilter, o, oc);
} else {
ist = input_streams[input_files[map->file_index]->ist_index + map->stream_index];
if(o->subtitle_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE)
continue;
if(o-> audio_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
......@@ -4488,13 +4983,15 @@ static void opt_output_file(void *optctx, const char *filename)
map->file_index, map->stream_index);
exit_program(1);
}
}
}
}
for (i = nb_output_streams - oc->nb_streams; i < nb_output_streams; i++) { //for all streams of this output file
AVDictionaryEntry *e;
ost = &output_streams[i];
ost = output_streams[i];
if ( ost->stream_copy
&& (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)
}
output_files = grow_array(output_files, sizeof(*output_files), &nb_output_files, nb_output_files + 1);
output_files[nb_output_files - 1].ctx = oc;
output_files[nb_output_files - 1].ost_index = nb_output_streams - oc->nb_streams;
output_files[nb_output_files - 1].recording_time = o->recording_time;
if (!(output_files[nb_output_files - 1] = av_mallocz(sizeof(*output_files[0]))))
exit_program(1);
output_files[nb_output_files - 1]->ctx = oc;
output_files[nb_output_files - 1]->ost_index = nb_output_streams - oc->nb_streams;
output_files[nb_output_files - 1]->recording_time = o->recording_time;
if (o->recording_time != INT64_MAX)
oc->duration = o->recording_time;
output_files[nb_output_files - 1].start_time = o->start_time;
output_files[nb_output_files - 1].limit_filesize = o->limit_filesize;
av_dict_copy(&output_files[nb_output_files - 1].opts, format_opts, 0);
output_files[nb_output_files - 1]->start_time = o->start_time;
output_files[nb_output_files - 1]->limit_filesize = o->limit_filesize;
av_dict_copy(&output_files[nb_output_files - 1]->opts, format_opts, 0);
/* check filename in case of an image number is expected */
if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
......@@ -4563,7 +5063,7 @@ static void opt_output_file(void *optctx, const char *filename)
/* open the file */
if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE,
&oc->interrupt_callback,
&output_files[nb_output_files - 1].opts)) < 0) {
&output_files[nb_output_files - 1]->opts)) < 0) {
print_error(filename, err);
exit_program(1);
}
......@@ -4572,7 +5072,7 @@ static void opt_output_file(void *optctx, const char *filename)
if (o->mux_preload) {
uint8_t buf[64];
snprintf(buf, sizeof(buf), "%d", (int)(o->mux_preload*AV_TIME_BASE));
av_dict_set(&output_files[nb_output_files - 1].opts, "preload", buf, 0);
av_dict_set(&output_files[nb_output_files - 1]->opts, "preload", buf, 0);
}
oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE);
......@@ -4585,7 +5085,7 @@ static void opt_output_file(void *optctx, const char *filename)
av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d while processing metadata maps\n", in_file_index);
exit_program(1);
}
copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc, in_file_index >= 0 ? input_files[in_file_index].ctx : NULL, o);
copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc, in_file_index >= 0 ? input_files[in_file_index]->ctx : NULL, o);
}
/* copy chapters */
......@@ -4594,7 +5094,7 @@ static void opt_output_file(void *optctx, const char *filename)
/* copy chapters from the first input file that has them*/
o->chapters_input_file = -1;
for (i = 0; i < nb_input_files; i++)
if (input_files[i].ctx->nb_chapters) {
if (input_files[i]->ctx->nb_chapters) {
o->chapters_input_file = i;
break;
}
......@@ -4605,23 +5105,23 @@ static void opt_output_file(void *optctx, const char *filename)
}
}
if (o->chapters_input_file >= 0)
copy_chapters(&input_files[o->chapters_input_file], &output_files[nb_output_files - 1],
copy_chapters(input_files[o->chapters_input_file], output_files[nb_output_files - 1],
!o->metadata_chapters_manual);
/* copy global metadata by default */
if (!o->metadata_global_manual && nb_input_files){
av_dict_copy(&oc->metadata, input_files[0].ctx->metadata,
av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata,
AV_DICT_DONT_OVERWRITE);
if(o->recording_time != INT64_MAX)
av_dict_set(&oc->metadata, "duration", NULL, 0);
}
if (!o->metadata_streams_manual)
for (i = output_files[nb_output_files - 1].ost_index; i < nb_output_streams; i++) {
for (i = output_files[nb_output_files - 1]->ost_index; i < nb_output_streams; i++) {
InputStream *ist;
if (output_streams[i].source_index < 0) /* this is true e.g. for attached files */
if (output_streams[i]->source_index < 0) /* this is true e.g. for attached files */
continue;
ist = &input_streams[output_streams[i].source_index];
av_dict_copy(&output_streams[i].st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
ist = input_streams[output_streams[i]->source_index];
av_dict_copy(&output_streams[i]->st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
}
/* process manually set metadata */
......@@ -4764,8 +5264,8 @@ static int opt_target(OptionsContext *o, const char *opt, const char *arg)
if (nb_input_files) {
int i, j, fr;
for (j = 0; j < nb_input_files; j++) {
for (i = 0; i < input_files[j].nb_streams; i++) {
AVCodecContext *c = input_files[j].ctx->streams[i]->codec;
for (i = 0; i < input_files[j]->nb_streams; i++) {
AVCodecContext *c = input_files[j]->ctx->streams[i]->codec;
if (c->codec_type != AVMEDIA_TYPE_VIDEO)
continue;
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
return ret;
}
static int opt_filter_complex(const char *opt, const char *arg)
{
filtergraphs = grow_array(filtergraphs, sizeof(*filtergraphs),
&nb_filtergraphs, nb_filtergraphs + 1);
if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0]))))
return AVERROR(ENOMEM);
filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1;
filtergraphs[nb_filtergraphs - 1]->graph_desc = arg;
return 0;
}
#define OFFSET(x) offsetof(OptionsContext, x)
static const OptionDef options[] = {
/* main options */
......@@ -5131,6 +5642,7 @@ static const OptionDef options[] = {
{ "qscale", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_qscale}, "use fixed quality scale (VBR)", "q" },
{ "profile", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_profile}, "set profile", "profile" },
{ "filter", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(filters)}, "set stream filterchain", "filter_list" },
{ "filter_complex", HAS_ARG | OPT_EXPERT, {(void*)opt_filter_complex}, "create a complex filtergraph", "graph_description" },
{ "stats", OPT_BOOL, {&print_stats}, "print progress report during encoding", },
{ "attach", HAS_ARG | OPT_FUNC2, {(void*)opt_attach}, "add an attachment to the output file", "filename" },
{ "dump_attachment", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(dump_attachment)}, "extract an attachment into a file", "filename" },
......@@ -5274,7 +5786,7 @@ int main(int argc, char **argv)
}
current_time = ti = getutime();
if (transcode(output_files, nb_output_files, input_files, nb_input_files) < 0)
if (transcode() < 0)
exit_program(1);
ti = getutime() - ti;
if (do_benchmark) {
......
......@@ -1740,9 +1740,9 @@ static AVFilter input_filter =
static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters)
{
static const enum PixelFormat pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
char sws_flags_str[128];
int ret;
enum PixelFormat pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
AVFilterContext *filt_src = NULL, *filt_out = NULL;
snprintf(sws_flags_str, sizeof(sws_flags_str), "flags=%d", sws_flags);
......
......@@ -242,7 +242,7 @@ static int link_filter_inouts(AVFilterContext *filt_ctx,
} else {
p->filter_ctx = filt_ctx;
p->pad_idx = pad;
insert_inout(open_inputs, p);
append_inout(open_inputs, &p);
}
}
......
......@@ -165,9 +165,9 @@ static av_cold int vsink_init(AVFilterContext *ctx, const char *args, void *opaq
av_unused AVBufferSinkParams *params;
if (!opaque) {
av_log(ctx, AV_LOG_ERROR,
av_log(ctx, AV_LOG_WARNING,
"No opaque field provided\n");
return AVERROR(EINVAL);
buf->pixel_fmts = NULL;
} else {
#if FF_API_OLD_VSINK_API
const int *pixel_fmts = (const enum PixelFormat *)opaque;
......@@ -194,7 +194,11 @@ static int vsink_query_formats(AVFilterContext *ctx)
{
BufferSinkContext *buf = ctx->priv;
avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(buf->pixel_fmts));
if (buf->pixel_fmts)
avfilter_set_common_pixel_formats(ctx, avfilter_make_format_list(buf->pixel_fmts));
else
avfilter_default_query_formats(ctx);
return 0;
}
......
......@@ -73,9 +73,9 @@ do_video_encoding mpeg2threadivlc.mpg "-qscale 10 -vcodec mpeg2video -f mpeg1vid
do_video_decoding
# mpeg2 encoding interlaced
file=${outfile}mpeg2reuse.mpg
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
do_video_decoding
#file=${outfile}mpeg2reuse.mpg
#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
#do_video_decoding
fi
if [ -n "$do_msmpeg4v2" ] ; then
......
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 20829
ret: 0 st:-1 flags:0 ts:-1.000000
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 20829
ret: 0 st:-1 flags:1 ts: 1.894167
ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 337078 size: 26840
ret: 0 st: 0 flags:0 ts: 0.788334
ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 141401 size: 23537
ret:-1 st: 0 flags:1 ts:-0.317499
ret:-1 st:-1 flags:0 ts: 2.576668
ret: 0 st:-1 flags:1 ts: 1.470835
ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 232037 size: 26192
ret: 0 st: 0 flags:0 ts: 0.365002
ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 63793 size: 21295
ret:-1 st: 0 flags:1 ts:-0.740831
ret:-1 st:-1 flags:0 ts: 2.153336
ret: 0 st:-1 flags:1 ts: 1.047503
ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 141401 size: 23537
ret: 0 st: 0 flags:0 ts:-0.058330
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 20829
ret: 0 st: 0 flags:1 ts: 2.835837
ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 337078 size: 26840
ret: 0 st:-1 flags:0 ts: 1.730004
ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 337078 size: 26840
ret: 0 st:-1 flags:1 ts: 0.624171
ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 63793 size: 21295
ret: 0 st: 0 flags:0 ts:-0.481662
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 20829
ret: 0 st: 0 flags:1 ts: 2.412505
ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 337078 size: 26840
ret: 0 st:-1 flags:0 ts: 1.306672
ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 232037 size: 26192
ret: 0 st:-1 flags:1 ts: 0.200839
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 20829
ret: 0 st: 0 flags:0 ts:-0.904994
ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 20829
ret: 0 st: 0 flags:1 ts: 1.989173
ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 337078 size: 26840
ret: 0 st:-1 flags:0 ts: 0.883340
ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 232037 size: 26192
ret:-1 st:-1 flags:1 ts:-0.222493
ret:-1 st: 0 flags:0 ts: 2.671674
ret: 0 st: 0 flags:1 ts: 1.565841
ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 232037 size: 26192
ret: 0 st:-1 flags:0 ts: 0.460008
ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 141401 size: 23537
ret:-1 st:-1 flags:1 ts:-0.645825
......@@ -2,7 +2,3 @@
791773 ./tests/data/vsynth1/mpeg2threadivlc.mpg
d1658911ca83f5616c1d32abc40750de *./tests/data/mpeg2thread_ilace.vsynth1.out.yuv
stddev: 7.63 PSNR: 30.48 MAXDIFF: 110 bytes: 7603200/ 7603200
d119fe917dd81d1ff758b4ce684a8d9d *./tests/data/vsynth1/mpeg2reuse.mpg
2074636 ./tests/data/vsynth1/mpeg2reuse.mpg
92ced6afe8c02304943c400cce51a5f4 *./tests/data/mpeg2thread_ilace.vsynth1.out.yuv
stddev: 7.66 PSNR: 30.44 MAXDIFF: 111 bytes: 7603200/ 7603200
......@@ -2,7 +2,3 @@
178801 ./tests/data/vsynth2/mpeg2threadivlc.mpg
8c6a7ed2eb73bd18fd2bb9829464100d *./tests/data/mpeg2thread_ilace.vsynth2.out.yuv
stddev: 4.72 PSNR: 34.65 MAXDIFF: 72 bytes: 7603200/ 7603200
864d6bf2982a61e510003a518be65a2d *./tests/data/vsynth2/mpeg2reuse.mpg
383419 ./tests/data/vsynth2/mpeg2reuse.mpg
bb20fa080cfd2b0a687ea7376ff4f902 *./tests/data/mpeg2thread_ilace.vsynth2.out.yuv
stddev: 4.73 PSNR: 34.63 MAXDIFF: 72 bytes: 7603200/ 7603200
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment