+#if CONFIG_AVFILTER
+typedef struct {
+ int pix_fmt;
+} FilterOutPriv;
+
+
+static int output_init(AVFilterContext *ctx, const char *args, void *opaque)
+{
+ FilterOutPriv *priv = ctx->priv;
+
+ if(!opaque) return -1;
+
+ priv->pix_fmt = *((int *)opaque);
+
+ return 0;
+}
+
+static void output_end_frame(AVFilterLink *link)
+{
+}
+
+static int output_query_formats(AVFilterContext *ctx)
+{
+ FilterOutPriv *priv = ctx->priv;
+ enum PixelFormat pix_fmts[] = { priv->pix_fmt, PIX_FMT_NONE };
+
+ avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
+ return 0;
+}
+
+static int get_filtered_video_pic(AVFilterContext *ctx,
+ AVFilterBufferRef **picref, AVFrame *pic2,
+ uint64_t *pts)
+{
+ AVFilterBufferRef *pic;
+
+ if(avfilter_request_frame(ctx->inputs[0]))
+ return -1;
+ if(!(pic = ctx->inputs[0]->cur_buf))
+ return -1;
+ *picref = pic;
+ ctx->inputs[0]->cur_buf = NULL;
+
+ *pts = pic->pts;
+
+ memcpy(pic2->data, pic->data, sizeof(pic->data));
+ memcpy(pic2->linesize, pic->linesize, sizeof(pic->linesize));
+ pic2->interlaced_frame = pic->video->interlaced;
+ pic2->top_field_first = pic->video->top_field_first;
+
+ return 1;
+}
+
+static AVFilter output_filter =
+{
+ .name = "ffmpeg_output",
+
+ .priv_size = sizeof(FilterOutPriv),
+ .init = output_init,
+
+ .query_formats = output_query_formats,
+
+ .inputs = (AVFilterPad[]) {{ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .end_frame = output_end_frame,
+ .min_perms = AV_PERM_READ, },
+ { .name = NULL }},
+ .outputs = (AVFilterPad[]) {{ .name = NULL }},
+};
+
+static int configure_filters(AVInputStream *ist, AVOutputStream *ost)
+{
+ AVFilterContext *last_filter, *filter;
+ /** filter graph containing all filters including input & output */
+ AVCodecContext *codec = ost->st->codec;
+ AVCodecContext *icodec = ist->st->codec;
+ char args[255];
+ int ret;
+
+ graph = av_mallocz(sizeof(AVFilterGraph));
+
+ if ((ret = avfilter_open(&ist->input_video_filter, avfilter_get_by_name("buffer"), "src")) < 0)
+ return ret;
+ if ((ret = avfilter_open(&ist->output_video_filter, &output_filter, "out")) < 0)
+ return ret;
+
+ snprintf(args, 255, "%d:%d:%d", ist->st->codec->width,
+ ist->st->codec->height, ist->st->codec->pix_fmt);
+ if ((ret = avfilter_init_filter(ist->input_video_filter, args, NULL)) < 0)
+ return ret;
+ if ((ret = avfilter_init_filter(ist->output_video_filter, NULL, &codec->pix_fmt)) < 0)
+ return ret;
+
+ /* add input and output filters to the overall graph */
+ avfilter_graph_add_filter(graph, ist->input_video_filter);
+ avfilter_graph_add_filter(graph, ist->output_video_filter);
+
+ last_filter = ist->input_video_filter;
+
+ if (ost->video_crop) {
+ snprintf(args, 255, "%d:%d:%d:%d",
+ codec->width, codec->height,
+ ost->leftBand, ost->topBand);
+ if ((ret = avfilter_open(&filter, avfilter_get_by_name("crop"), NULL)) < 0)
+ return ret;
+ if ((ret = avfilter_init_filter(filter, args, NULL)) < 0)
+ return ret;
+ if ((ret = avfilter_link(last_filter, 0, filter, 0)) < 0)
+ return ret;
+ last_filter = filter;
+ avfilter_graph_add_filter(graph, last_filter);
+ }
+
+ if((codec->width !=
+ icodec->width - (frame_leftBand + frame_rightBand)) ||
+ (codec->height != icodec->height - (frame_topBand + frame_bottomBand))) {
+ snprintf(args, 255, "%d:%d:flags=0x%X",
+ codec->width,
+ codec->height,
+ (int)av_get_int(sws_opts, "sws_flags", NULL));
+ if ((ret = avfilter_open(&filter, avfilter_get_by_name("scale"), NULL)) < 0)
+ return ret;
+ if ((ret = avfilter_init_filter(filter, args, NULL)) < 0)
+ return ret;
+ if ((ret = avfilter_link(last_filter, 0, filter, 0)) < 0)
+ return ret;
+ last_filter = filter;
+ avfilter_graph_add_filter(graph, last_filter);
+ }
+
+ snprintf(args, sizeof(args), "flags=0x%X", (int)av_get_int(sws_opts, "sws_flags", NULL));
+ graph->scale_sws_opts = av_strdup(args);
+
+ if (vfilters) {
+ AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut));
+ AVFilterInOut *inputs = av_malloc(sizeof(AVFilterInOut));
+
+ outputs->name = av_strdup("in");
+ outputs->filter = last_filter;
+ outputs->pad_idx = 0;
+ outputs->next = NULL;
+
+ inputs->name = av_strdup("out");
+ inputs->filter = ist->output_video_filter;
+ inputs->pad_idx = 0;
+ inputs->next = NULL;
+
+ if ((ret = avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL)) < 0)
+ return ret;
+ av_freep(&vfilters);
+ } else {
+ if ((ret = avfilter_link(last_filter, 0, ist->output_video_filter, 0)) < 0)
+ return ret;
+ }
+
+ /* configure all the filter links */
+ if ((ret = avfilter_graph_check_validity(graph, NULL)) < 0)
+ return ret;
+ if ((ret = avfilter_graph_config_formats(graph, NULL)) < 0)
+ return ret;
+ if ((ret = avfilter_graph_config_links(graph, NULL)) < 0)
+ return ret;
+
+ codec->width = ist->output_video_filter->inputs[0]->w;
+ codec->height = ist->output_video_filter->inputs[0]->h;
+
+ return 0;
+}
+#endif /* CONFIG_AVFILTER */
+