int configure_filtergraph(FilterGraph *fg) { AVFilterInOut *inputs, *outputs, *cur; int ret, i, init = !fg->graph, simple = !fg->graph_desc; const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : fg->graph_desc; avfilter_graph_free(&fg->graph); if (!(fg->graph = avfilter_graph_alloc())) return AVERROR(ENOMEM); if (simple) { OutputStream *ost = fg->outputs[0]->ost; char args[255]; snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags); fg->graph->scale_sws_opts = av_strdup(args); } if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) return ret; if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' does not have " "exactly one input and output.\n", graph_desc); return AVERROR(EINVAL); } for (cur = inputs; !simple && init && cur; cur = cur->next) init_input_filter(fg, cur); for (cur = inputs, i = 0; cur; cur = cur->next, i++) if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) return ret; avfilter_inout_free(&inputs); if (!init || simple) { /* 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(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; }
int configure_filtergraph(FilterGraph *fg) { AVFilterInOut *inputs, *outputs, *cur; int ret, i, simple = !fg->graph_desc; const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : fg->graph_desc; avfilter_graph_free(&fg->graph); if (!(fg->graph = avfilter_graph_alloc())) return AVERROR(ENOMEM); if (simple) { OutputStream *ost = fg->outputs[0]->ost; char args[512]; AVDictionaryEntry *e = NULL; snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags); fg->graph->scale_sws_opts = av_strdup(args); args[0] = '\0'; while ((e = av_dict_get(fg->outputs[0]->ost->resample_opts, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); } if (strlen(args)) args[strlen(args) - 1] = '\0'; fg->graph->resample_lavr_opts = av_strdup(args); } if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) return ret; if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' does not have " "exactly one input and output.\n", graph_desc); return AVERROR(EINVAL); } for (cur = inputs, i = 0; cur; cur = cur->next, i++) if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) return ret; avfilter_inout_free(&inputs); 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; return 0; }
int configure_filter(struct liveStream *ctx) { int ret = 0; int i = 0; /** Input Id */ long in_id; AVFilterInOut *outputs; AVFilterInOut *inputs; AVFilterInOut *cur; take_filter_lock(&ctx->filter_lock); avfilter_graph_free(&ctx->filter_graph); ctx->filter_graph = avfilter_graph_alloc(); if (NULL == ctx->filter_graph) { av_log(NULL,AV_LOG_ERROR,"Unable to allocate Filter\n"); return -1; } ret = avfilter_graph_parse2(ctx->filter_graph, ctx->graph_desc.str, &inputs, &outputs); if(ret < 0) return ret; for (i = 0,cur = inputs; cur; cur = cur->next,i++) { in_id = strtol(cur->name,NULL,0); if(in_id < 0 || in_id >= ctx->nb_input) { /** Invalid index of video provided */ ret = -1; break; } configure_input_filter(ctx, in_id, cur); } avfilter_inout_free(&inputs); ret = configure_output_filter(ctx,outputs); if(ret < 0) { printf("unable to configure output filter\n"); return ret; } avfilter_inout_free(&outputs); if ((ret = avfilter_graph_config(ctx->filter_graph, NULL)) < 0) return ret; give_filter_lock(&ctx->filter_lock); return 0; }
int init_complex_filtergraph(FilterGraph *fg) { AVFilterInOut *inputs, *outputs, *cur; AVFilterGraph *graph; int ret = 0; /* this graph is only used for determining the kinds of inputs * and outputs we have, and is discarded on exit from this function */ graph = avfilter_graph_alloc(); if(!graph) { return AVERROR(ENOMEM); } ret = avfilter_graph_parse2(graph, fg->graph_desc, &inputs, &outputs); if(ret < 0) { goto fail; } for(cur = inputs; cur; cur = cur->next) { init_input_filter(fg, cur); } for(cur = outputs; cur;) { GROW_ARRAY(fg->outputs, fg->nb_outputs); fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0])); if(!fg->outputs[fg->nb_outputs - 1]) { exit_program(1); } fg->outputs[fg->nb_outputs - 1]->graph = fg; fg->outputs[fg->nb_outputs - 1]->out_tmp = cur; fg->outputs[fg->nb_outputs - 1]->type = avfilter_pad_get_type(cur->filter_ctx->output_pads, cur->pad_idx); cur = cur->next; fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL; } fail: avfilter_inout_free(&inputs); avfilter_graph_free(&graph); return ret; }
bool MovieDecoder::initFilterGraph(enum AVPixelFormat pixfmt, int width, int height) { AVFilterInOut *inputs = nullptr, *outputs = nullptr; deleteFilterGraph(); m_filterGraph = avfilter_graph_alloc(); QByteArray arguments("buffer="); arguments += "video_size=" + QByteArray::number(width) + "x" + QByteArray::number(height) + ":"; arguments += "pix_fmt=" + QByteArray::number(pixfmt) + ":"; arguments += "time_base=1/1:pixel_aspect=0/1[in];"; arguments += "[in]yadif[out];"; arguments += "[out]buffersink"; int ret = avfilter_graph_parse2(m_filterGraph, arguments.constData(), &inputs, &outputs); if (ret < 0) { qWarning() << "Unable to parse filter graph"; return false; } if(inputs || outputs) return -1; ret = avfilter_graph_config(m_filterGraph, nullptr); if (ret < 0) { qWarning() << "Unable to validate filter graph"; return false; } m_bufferSourceContext = avfilter_graph_get_filter(m_filterGraph, "Parsed_buffer_0"); m_bufferSinkContext = avfilter_graph_get_filter(m_filterGraph, "Parsed_buffersink_2"); if (!m_bufferSourceContext || !m_bufferSinkContext) { qWarning() << "Unable to get source or sink"; return false; } m_filterFrame = av_frame_alloc(); m_lastWidth = width; m_lastHeight = height; m_lastPixfmt = pixfmt; return true; }
int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut *open_inputs, AVFilterInOut *open_outputs, void *log_ctx) { int ret; AVFilterInOut *cur, *match, *inputs = NULL, *outputs = NULL; if ((ret = avfilter_graph_parse2(graph, filters, &inputs, &outputs)) < 0) goto fail; /* First input can be omitted if it is "[in]" */ if (inputs && !inputs->name) inputs->name = av_strdup("in"); for (cur = inputs; cur; cur = cur->next) { if (!cur->name) { av_log(log_ctx, AV_LOG_ERROR, "Not enough inputs specified for the \"%s\" filter.\n", cur->filter_ctx->filter->name); ret = AVERROR(EINVAL); goto fail; } if (!(match = extract_inout(cur->name, &open_outputs))) continue; ret = avfilter_link(match->filter_ctx, match->pad_idx, cur->filter_ctx, cur->pad_idx); avfilter_inout_free(&match); if (ret < 0) goto fail; } /* Last output can be omitted if it is "[out]" */ if (outputs && !outputs->name) outputs->name = av_strdup("out"); for (cur = outputs; cur; cur = cur->next) { if (!cur->name) { av_log(log_ctx, AV_LOG_ERROR, "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", filters); ret = AVERROR(EINVAL); goto fail; } if (!(match = extract_inout(cur->name, &open_inputs))) continue; ret = avfilter_link(cur->filter_ctx, cur->pad_idx, match->filter_ctx, match->pad_idx); avfilter_inout_free(&match); if (ret < 0) goto fail; } fail: if (ret < 0) { while (graph->nb_filters) avfilter_free(graph->filters[0]); av_freep(&graph->filters); } avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); avfilter_inout_free(&open_inputs); avfilter_inout_free(&open_outputs); return ret; #else int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs, void *log_ctx) { return avfilter_graph_parse_ptr(graph, filters, inputs, outputs, log_ctx); #endif } int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters, AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr, void *log_ctx) { int index = 0, ret = 0; char chr = 0; AVFilterInOut *curr_inputs = NULL; AVFilterInOut *open_inputs = open_inputs_ptr ? *open_inputs_ptr : NULL; AVFilterInOut *open_outputs = open_outputs_ptr ? *open_outputs_ptr : NULL; if ((ret = parse_sws_flags(&filters, graph)) < 0) goto end; do { AVFilterContext *filter; const char *filterchain = filters; filters += strspn(filters, WHITESPACES); if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0) goto end; if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0) goto end; if (filter->nb_inputs == 1 && !curr_inputs && !index) { /* First input pad, assume it is "[in]" if not specified */ const char *tmp = "[in]"; if ((ret = parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx)) < 0) goto end; } if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0) goto end; if ((ret = parse_outputs(&filters, &curr_inputs, &open_inputs, &open_outputs, log_ctx)) < 0) goto end; filters += strspn(filters, WHITESPACES); chr = *filters++; if (chr == ';' && curr_inputs) { av_log(log_ctx, AV_LOG_ERROR, "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", filterchain); ret = AVERROR(EINVAL); goto end; } index++; } while (chr == ',' || chr == ';'); if (chr) { av_log(log_ctx, AV_LOG_ERROR, "Unable to parse graph description substring: \"%s\"\n", filters - 1); ret = AVERROR(EINVAL); goto end; } if (curr_inputs) { /* Last output pad, assume it is "[out]" if not specified */ const char *tmp = "[out]"; if ((ret = parse_outputs(&tmp, &curr_inputs, &open_inputs, &open_outputs, log_ctx)) < 0) goto end; } end: /* clear open_in/outputs only if not passed as parameters */ if (open_inputs_ptr) *open_inputs_ptr = open_inputs; else avfilter_inout_free(&open_inputs); if (open_outputs_ptr) *open_outputs_ptr = open_outputs; else avfilter_inout_free(&open_outputs); avfilter_inout_free(&curr_inputs); if (ret < 0) { while (graph->nb_filters) avfilter_free(graph->filters[0]); av_freep(&graph->filters); } return ret; }
int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut *open_inputs, AVFilterInOut *open_outputs, void *log_ctx) { int ret; AVFilterInOut *cur, *match, *inputs = NULL, *outputs = NULL; if ((ret = avfilter_graph_parse2(graph, filters, &inputs, &outputs)) < 0) goto fail; /* First input can be omitted if it is "[in]" */ if (inputs && !inputs->name) inputs->name = av_strdup("in"); for (cur = inputs; cur; cur = cur->next) { if (!cur->name) { av_log(log_ctx, AV_LOG_ERROR, "Not enough inputs specified for the \"%s\" filter.\n", cur->filter_ctx->filter->name); ret = AVERROR(EINVAL); goto fail; } if (!(match = extract_inout(cur->name, &open_outputs))) continue; ret = avfilter_link(match->filter_ctx, match->pad_idx, cur->filter_ctx, cur->pad_idx); avfilter_inout_free(&match); if (ret < 0) goto fail; } /* Last output can be omitted if it is "[out]" */ if (outputs && !outputs->name) outputs->name = av_strdup("out"); for (cur = outputs; cur; cur = cur->next) { if (!cur->name) { av_log(log_ctx, AV_LOG_ERROR, "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", filters); ret = AVERROR(EINVAL); goto fail; } if (!(match = extract_inout(cur->name, &open_inputs))) continue; ret = avfilter_link(cur->filter_ctx, cur->pad_idx, match->filter_ctx, match->pad_idx); avfilter_inout_free(&match); if (ret < 0) goto fail; } fail: if (ret < 0) { for (; graph->filter_count > 0; graph->filter_count--) avfilter_free(graph->filters[graph->filter_count - 1]); av_freep(&graph->filters); } avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); avfilter_inout_free(&open_inputs); avfilter_inout_free(&open_outputs); return ret; }
// Parse the user-provided filter graph, and populate the unlinked filter pads. static void precreate_graph(struct lavfi *c, bool first_init) { assert(!c->graph); c->failed = false; c->graph = avfilter_graph_alloc(); if (!c->graph) abort(); if (mp_set_avopts(c->log, c->graph, c->graph_opts) < 0) goto error; if (c->direct_filter) { AVFilterContext *filter = avfilter_graph_alloc_filter(c->graph, avfilter_get_by_name(c->graph_string), "filter"); if (!filter) { MP_FATAL(c, "filter '%s' not found or failed to allocate\n", c->graph_string); goto error; } if (mp_set_avopts_pos(c->log, filter, filter->priv, c->direct_filter_opts) < 0) goto error; if (avfilter_init_str(filter, NULL) < 0) { MP_FATAL(c, "filter failed to initialize\n"); goto error; } add_pads_direct(c, MP_PIN_IN, filter, filter->input_pads, filter->nb_inputs, first_init); add_pads_direct(c, MP_PIN_OUT, filter, filter->output_pads, filter->nb_outputs, first_init); } else { AVFilterInOut *in = NULL, *out = NULL; if (avfilter_graph_parse2(c->graph, c->graph_string, &in, &out) < 0) { MP_FATAL(c, "parsing the filter graph failed\n"); goto error; } add_pads(c, MP_PIN_IN, in, first_init); add_pads(c, MP_PIN_OUT, out, first_init); avfilter_inout_free(&in); avfilter_inout_free(&out); } for (int n = 0; n < c->num_all_pads; n++) c->failed |= !c->all_pads[n]->filter; if (c->failed) goto error; return; error: free_graph(c); c->failed = true; mp_filter_internal_mark_failed(c->f); return; }
int configure_filtergraph(FilterGraph *fg) { AVFilterInOut *inputs, *outputs, *cur; int ret, i, simple = !fg->graph_desc; const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : fg->graph_desc; avfilter_graph_free(&fg->graph); if (!(fg->graph = avfilter_graph_alloc())) return AVERROR(ENOMEM); if (simple) { OutputStream *ost = fg->outputs[0]->ost; char args[512]; AVDictionaryEntry *e = NULL; args[0] = 0; while ((e = av_dict_get(ost->sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); } if (strlen(args)) args[strlen(args)-1] = 0; fg->graph->scale_sws_opts = av_strdup(args); args[0] = 0; while ((e = av_dict_get(ost->swr_opts, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); } if (strlen(args)) args[strlen(args)-1] = 0; av_opt_set(fg->graph, "aresample_swr_opts", args, 0); args[0] = '\0'; while ((e = av_dict_get(fg->outputs[0]->ost->resample_opts, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); } if (strlen(args)) args[strlen(args) - 1] = '\0'; fg->graph->resample_lavr_opts = av_strdup(args); e = av_dict_get(ost->encoder_opts, "threads", NULL, 0); if (e) av_opt_set(fg->graph, "threads", e->value, 0); } if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) return ret; if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { const char *num_inputs; const char *num_outputs; if (!outputs) { num_outputs = "0"; } else if (outputs->next) { num_outputs = ">1"; } else { num_outputs = "1"; } if (!inputs) { num_inputs = "0"; } else if (inputs->next) { num_inputs = ">1"; } else { num_inputs = "1"; } av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' was expected " "to have exactly 1 input and 1 output." " However, it had %s input(s) and %s output(s)." " Please adjust, or use a complex filtergraph (-filter_complex) instead.\n", graph_desc, num_inputs, num_outputs); return AVERROR(EINVAL); } for (cur = inputs, i = 0; cur; cur = cur->next, i++) if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) { avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); return ret; } avfilter_inout_free(&inputs); 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; fg->reconfiguration = 1; for (i = 0; i < fg->nb_outputs; i++) { OutputStream *ost = fg->outputs[i]->ost; if (!ost->enc) { /* identical to the same check in ffmpeg.c, needed because complex filter graphs are initialized earlier */ av_log(NULL, AV_LOG_ERROR, "Encoder (codec %s) not found for output stream #%d:%d\n", avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index); return AVERROR(EINVAL); } if (ost->enc->type == AVMEDIA_TYPE_AUDIO && !(ost->enc->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) av_buffersink_set_frame_size(ost->filter->filter, ost->enc_ctx->frame_size); } return 0; }