static int query_formats(AVFilterGraph *graph, AVClass *log_ctx) { int i, j; int scaler_count = 0; char inst_name[30]; /* ask all the sub-filters for their supported colorspaces */ for(i = 0; i < graph->filter_count; i ++) { if(graph->filters[i]->filter->query_formats) graph->filters[i]->filter->query_formats(graph->filters[i]); else avfilter_default_query_formats(graph->filters[i]); } /* go through and merge as many format lists as possible */ for(i = 0; i < graph->filter_count; i ++) { AVFilterContext *filter = graph->filters[i]; for(j = 0; j < filter->input_count; j ++) { AVFilterLink *link = filter->inputs[j]; if(link && link->in_formats != link->out_formats) { if(!avfilter_merge_formats(link->in_formats, link->out_formats)) { AVFilterContext *scale; char scale_args[256]; /* couldn't merge format lists. auto-insert scale filter */ snprintf(inst_name, sizeof(inst_name), "auto-inserted scaler %d", scaler_count++); scale = avfilter_open(avfilter_get_by_name("scale"),inst_name); snprintf(scale_args, sizeof(scale_args), "0:0:%s", graph->scale_sws_opts); if(!scale || scale->filter->init(scale, scale_args, NULL) || avfilter_insert_filter(link, scale, 0, 0)) { avfilter_destroy(scale); return -1; } if (avfilter_graph_add_filter(graph, scale) < 0) return -1; scale->filter->query_formats(scale); if (((link = scale-> inputs[0]) && !avfilter_merge_formats(link->in_formats, link->out_formats)) || ((link = scale->outputs[0]) && !avfilter_merge_formats(link->in_formats, link->out_formats))) { av_log(log_ctx, AV_LOG_ERROR, "Impossible to convert between the formats supported by the filter " "'%s' and the filter '%s'\n", link->src->name, link->dst->name); return -1; } } } } } return 0; }
/** * Create an instance of a filter, initialize and insert it in the * filtergraph in *ctx. * * @param ctx the filtergraph context * @param put here a filter context in case of successful creation and configuration, NULL otherwise. * @param index an index which is supposed to be unique for each filter instance added to the filtergraph * @param filt_name the name of the filter to create * @param args the arguments provided to the filter during its initialization * @param log_ctx the log context to use * @return 0 in case of success, a negative AVERROR code otherwise */ static int create_filter(AVFilterContext **filt_ctx, AVFilterGraph *ctx, int index, const char *filt_name, const char *args, void *log_ctx) { AVFilter *filt; char inst_name[30]; char tmp_args[256]; int ret; snprintf(inst_name, sizeof(inst_name), "Parsed filter %d %s", index, filt_name); filt = avfilter_get_by_name(filt_name); if (!filt) { av_log(log_ctx, AV_LOG_ERROR, "No such filter: '%s'\n", filt_name); return AVERROR(EINVAL); } ret = avfilter_open(filt_ctx, filt, inst_name); if (!*filt_ctx) { av_log(log_ctx, AV_LOG_ERROR, "Error creating filter '%s'\n", filt_name); return ret; } if ((ret = avfilter_graph_add_filter(ctx, *filt_ctx)) < 0) { avfilter_free(*filt_ctx); return ret; } if (!strcmp(filt_name, "scale") && args && !strstr(args, "flags") && ctx->scale_sws_opts) { snprintf(tmp_args, sizeof(tmp_args), "%s:%s", args, ctx->scale_sws_opts); args = tmp_args; } if ((ret = avfilter_init_filter(*filt_ctx, args, NULL)) < 0) { av_log(log_ctx, AV_LOG_ERROR, "Error initializing filter '%s' with args '%s'\n", filt_name, args); return ret; } return 0; }
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, AVFilter *filt, const char *name, const char *args, void *opaque, AVFilterGraph *graph_ctx) { int ret; if ((ret = avfilter_open(filt_ctx, filt, name)) < 0) goto fail; if ((ret = avfilter_init_filter(*filt_ctx, args, opaque)) < 0) goto fail; if ((ret = avfilter_graph_add_filter(graph_ctx, *filt_ctx)) < 0) goto fail; return 0; fail: if (*filt_ctx) avfilter_free(*filt_ctx); *filt_ctx = NULL; return ret; }
static int insert_filter(ABufferSourceContext *abuffer, AVFilterLink *link, AVFilterContext **filt_ctx, const char *filt_name) { int ret; if ((ret = avfilter_open(filt_ctx, avfilter_get_by_name(filt_name), NULL)) < 0) return ret; link->src->outputs[0] = NULL; if ((ret = avfilter_link(link->src, 0, *filt_ctx, 0)) < 0) { link->src->outputs[0] = link; return ret; } set_link_source(*filt_ctx, link); if ((ret = reconfigure_filter(abuffer, *filt_ctx)) < 0) { avfilter_free(*filt_ctx); return ret; } return 0; }
int av_vsrc_buffer_add_video_buffer_ref(AVFilterContext *buffer_filter, AVFilterBufferRef *picref, int flags) { BufferSourceContext *c = buffer_filter->priv; AVFilterLink *outlink = buffer_filter->outputs[0]; int ret; if (c->picref) { if (flags & AV_VSRC_BUF_FLAG_OVERWRITE) { avfilter_unref_buffer(c->picref); c->picref = NULL; } else { av_log(buffer_filter, AV_LOG_ERROR, "Buffering several frames is not supported. " "Please consume all available frames before adding a new one.\n"); return AVERROR(EINVAL); } } if (picref->video->w != c->w || picref->video->h != c->h || picref->format != c->pix_fmt) { AVFilterContext *scale = buffer_filter->outputs[0]->dst; AVFilterLink *link; char scale_param[1024]; av_log(buffer_filter, AV_LOG_INFO, "Buffer video input changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name, picref->video->w, picref->video->h, av_pix_fmt_descriptors[picref->format].name); if (!scale || strcmp(scale->filter->name, "scale")) { AVFilter *f = avfilter_get_by_name("scale"); av_log(buffer_filter, AV_LOG_INFO, "Inserting scaler filter\n"); if ((ret = avfilter_open(&scale, f, "Input equalizer")) < 0) return ret; snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s", c->w, c->h, c->sws_param); if ((ret = avfilter_init_filter(scale, scale_param, NULL)) < 0) { avfilter_free(scale); return ret; } if ((ret = avfilter_insert_filter(buffer_filter->outputs[0], scale, 0, 0)) < 0) { avfilter_free(scale); return ret; } scale->outputs[0]->time_base = scale->inputs[0]->time_base; scale->outputs[0]->format= c->pix_fmt; } else if (!strcmp(scale->filter->name, "scale")) { snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s", scale->outputs[0]->w, scale->outputs[0]->h, c->sws_param); scale->filter->init(scale, scale_param, NULL); } c->pix_fmt = scale->inputs[0]->format = picref->format; c->w = scale->inputs[0]->w = picref->video->w; c->h = scale->inputs[0]->h = picref->video->h; link = scale->outputs[0]; if ((ret = link->srcpad->config_props(link)) < 0) return ret; } c->picref = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, picref->video->w, picref->video->h); av_image_copy(c->picref->data, c->picref->linesize, picref->data, picref->linesize, picref->format, picref->video->w, picref->video->h); avfilter_copy_buffer_ref_props(c->picref, picref); return 0; }
int av_vsrc_buffer_add_frame2(AVFilterContext *buffer_filter, AVFrame *frame, int64_t pts, AVRational pixel_aspect, int width, int height, enum PixelFormat pix_fmt, const char *sws_param) { BufferSourceContext *c = buffer_filter->priv; int ret; if (c->has_frame) { av_log(buffer_filter, AV_LOG_ERROR, "Buffering several frames is not supported. " "Please consume all available frames before adding a new one.\n" ); //return -1; } if(width != c->w || height != c->h || pix_fmt != c->pix_fmt){ AVFilterContext *scale= buffer_filter->outputs[0]->dst; AVFilterLink *link; av_log(buffer_filter, AV_LOG_INFO, "Changing filter graph input to accept %dx%d %d (%d %d)\n", width,height,pix_fmt, c->pix_fmt, scale->outputs[0]->format); if(!scale || strcmp(scale->filter->name,"scale")){ AVFilter *f= avfilter_get_by_name("scale"); av_log(buffer_filter, AV_LOG_INFO, "Inserting scaler filter\n"); if(avfilter_open(&scale, f, "Input equalizer") < 0) return -1; if((ret=avfilter_init_filter(scale, sws_param, NULL))<0){ avfilter_free(scale); return ret; } if((ret=avfilter_insert_filter(buffer_filter->outputs[0], scale, 0, 0))<0){ avfilter_free(scale); return ret; } scale->outputs[0]->format= c->pix_fmt; } c->pix_fmt= scale->inputs[0]->format= pix_fmt; c->w= scale->inputs[0]->w= width; c->h= scale->inputs[0]->h= height; link= scale->outputs[0]; if ((ret = link->srcpad->config_props(link)) < 0) return ret; } memcpy(c->frame.data , frame->data , sizeof(frame->data)); memcpy(c->frame.linesize, frame->linesize, sizeof(frame->linesize)); c->frame.interlaced_frame= frame->interlaced_frame; c->frame.top_field_first = frame->top_field_first; c->frame.key_frame = frame->key_frame; c->frame.pict_type = frame->pict_type; c->pts = pts; c->pixel_aspect = pixel_aspect; c->has_frame = 1; return 0; }
int main(int argc, char **argv) { AVFilter *filter; AVFilterContext *filter_ctx; const char *filter_name; const char *filter_args = NULL; int i; av_log_set_level(AV_LOG_DEBUG); if (!argv[1]) { fprintf(stderr, "Missing filter name as argument\n"); return 1; } filter_name = argv[1]; if (argv[2]) filter_args = argv[2]; avfilter_register_all(); /* get a corresponding filter and open it */ if (!(filter = avfilter_get_by_name(filter_name))) { fprintf(stderr, "Unrecognized filter with name '%s'\n", filter_name); return 1; } if (avfilter_open(&filter_ctx, filter, NULL) < 0) { fprintf(stderr, "Impossible to open filter with name '%s'\n", filter_name); return 1; } if (avfilter_init_filter(filter_ctx, filter_args, NULL) < 0) { fprintf(stderr, "Impossible to init filter '%s' with arguments '%s'\n", filter_name, filter_args); return 1; } /* create a link for each of the input pads */ for (i = 0; i < filter_ctx->input_count; i++) { AVFilterLink *link = av_mallocz(sizeof(AVFilterLink)); link->type = filter_ctx->filter->inputs[i].type; filter_ctx->inputs[i] = link; } for (i = 0; i < filter_ctx->output_count; i++) { AVFilterLink *link = av_mallocz(sizeof(AVFilterLink)); link->type = filter_ctx->filter->outputs[i].type; filter_ctx->outputs[i] = link; } if (filter->query_formats) filter->query_formats(filter_ctx); else avfilter_default_query_formats(filter_ctx); print_formats(filter_ctx); avfilter_free(filter_ctx); fflush(stdout); return 0; }
int av_vsrc_buffer_add_video_buffer_ref(AVFilterContext *buffer_filter, AVFilterBufferRef *picref, int flags) { BufferSourceContext *c = buffer_filter->priv; AVFilterLink *outlink = buffer_filter->outputs[0]; AVFilterBufferRef *buf; int ret; if (!picref) { c->eof = 1; return 0; } else if (c->eof) return AVERROR(EINVAL); if (!av_fifo_space(c->fifo) && (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) + sizeof(buf))) < 0) return ret; if (picref->video->w != c->w || picref->video->h != c->h || picref->format != c->pix_fmt) { AVFilterContext *scale = buffer_filter->outputs[0]->dst; AVFilterLink *link; char scale_param[1024]; av_log(buffer_filter, AV_LOG_INFO, "Buffer video input changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name, picref->video->w, picref->video->h, av_pix_fmt_descriptors[picref->format].name); if (!scale || strcmp(scale->filter->name, "scale")) { AVFilter *f = avfilter_get_by_name("scale"); av_log(buffer_filter, AV_LOG_INFO, "Inserting scaler filter\n"); if ((ret = avfilter_open(&scale, f, "Input equalizer")) < 0) return ret; c->scale = scale; snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s", c->w, c->h, c->sws_param); if ((ret = avfilter_init_filter(scale, scale_param, NULL)) < 0) { return ret; } if ((ret = avfilter_insert_filter(buffer_filter->outputs[0], scale, 0, 0)) < 0) { return ret; } scale->outputs[0]->time_base = scale->inputs[0]->time_base; scale->outputs[0]->format= c->pix_fmt; } else if (!strcmp(scale->filter->name, "scale")) { snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s", scale->outputs[0]->w, scale->outputs[0]->h, c->sws_param); scale->filter->init(scale, scale_param, NULL); } c->pix_fmt = scale->inputs[0]->format = picref->format; c->w = scale->inputs[0]->w = picref->video->w; c->h = scale->inputs[0]->h = picref->video->h; link = scale->outputs[0]; if ((ret = link->srcpad->config_props(link)) < 0) return ret; } buf = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, picref->video->w, picref->video->h); av_image_copy(buf->data, buf->linesize, (void*)picref->data, picref->linesize, picref->format, picref->video->w, picref->video->h); avfilter_copy_buffer_ref_props(buf, picref); if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0) { avfilter_unref_buffer(buf); return ret; } return 0; }
int main(int argc, char **argv) { AVFilter *filter; AVFilterContext *filter_ctx; const char *filter_name; const char *filter_args = NULL; int i, j; av_log_set_level(AV_LOG_DEBUG); if (!argv[1]) { fprintf(stderr, "Missing filter name as argument\n"); return 1; } filter_name = argv[1]; if (argv[2]) filter_args = argv[2]; avfilter_register_all(); /* get a corresponding filter and open it */ if (!(filter = avfilter_get_by_name(filter_name))) { fprintf(stderr, "Unrecognized filter with name '%s'\n", filter_name); return 1; } if (avfilter_open(&filter_ctx, filter, NULL) < 0) { fprintf(stderr, "Inpossible to open filter with name '%s'\n", filter_name); return 1; } if (avfilter_init_filter(filter_ctx, filter_args, NULL) < 0) { fprintf(stderr, "Impossible to init filter '%s' with arguments '%s'\n", filter_name, filter_args); return 1; } /* create a link for each of the input pads */ for (i = 0; i < filter_ctx->input_count; i++) { AVFilterLink *link = av_mallocz(sizeof(AVFilterLink)); link->type = filter_ctx->filter->inputs[i].type; filter_ctx->inputs[i] = link; } for (i = 0; i < filter_ctx->output_count; i++) { AVFilterLink *link = av_mallocz(sizeof(AVFilterLink)); link->type = filter_ctx->filter->outputs[i].type; filter_ctx->outputs[i] = link; } if (filter->query_formats) filter->query_formats(filter_ctx); else avfilter_default_query_formats(filter_ctx); /* print the supported formats in input */ for (i = 0; i < filter_ctx->input_count; i++) { AVFilterFormats *fmts = filter_ctx->inputs[i]->out_formats; for (j = 0; j < fmts->format_count; j++) printf("INPUT[%d] %s: %s\n", i, filter_ctx->filter->inputs[i].name, av_pix_fmt_descriptors[fmts->formats[j]].name); } /* print the supported formats in output */ for (i = 0; i < filter_ctx->output_count; i++) { AVFilterFormats *fmts = filter_ctx->outputs[i]->in_formats; for (j = 0; j < fmts->format_count; j++) printf("OUTPUT[%d] %s: %s\n", i, filter_ctx->filter->outputs[i].name, av_pix_fmt_descriptors[fmts->formats[j]].name); } avfilter_destroy(filter_ctx); fflush(stdout); return 0; }