Revision 7b470878 libavfilter/avfiltergraph.c

View differences:

libavfilter/avfiltergraph.c
58 58
    return lctx->graph->inputs[link->srcpad];
59 59
}
60 60

  
61
/** query the formats supported by a filter providing input to the graph */
62
static int *link_in_query_formats(AVFilterLink *link)
63
{
64
    AVFilterLink *link2 = get_extern_input_link(link);
65
    int *(*query_formats)(AVFilterLink *);
66

  
67
    if(!link2)
68
        return avfilter_make_format_list(0);
69

  
70
    if(!(query_formats = link2->src->output_pads[link2->srcpad].query_formats))
71
        query_formats = avfilter_default_query_output_formats;
72

  
73
    return query_formats(link2);
74
}
75

  
76 61
/** request a frame from a filter providing input to the graph */
77 62
static int link_in_request_frame(AVFilterLink *link)
78 63
{
......
112 97
    return lctx->graph->outputs[link->dstpad];
113 98
}
114 99

  
115
/** query the formats supported by a filter taking output from the graph */
116
static int *link_out_query_formats(AVFilterLink *link)
117
{
118
    AVFilterLink *link2 = get_extern_output_link(link);
119

  
120
    if(!link2)
121
        return avfilter_make_format_list(0);
122

  
123
    return link2->dst->input_pads[link2->dstpad].query_formats(link2);
124
}
125

  
126 100
static int link_out_config_props(AVFilterLink *link)
127 101
{
128 102
    AVFilterLink *link2 = get_extern_output_link(link);
......
224 198
        avfilter_draw_slice(link2, y, height);
225 199
}
226 200

  
227
static int *graph_in_query_formats(AVFilterLink *link)
228
{
229
    AVFilterLink *link2 = get_intern_input_link(link);
230

  
231
    if(!link2 || !link2->dst->input_pads[link2->dstpad].query_formats)
232
        return avfilter_make_format_list(0);
233
    return link2->dst->input_pads[link2->dstpad].query_formats(link2);
234
}
235

  
236 201
static int graph_in_config_props(AVFilterLink *link)
237 202
{
238 203
    AVFilterLink *link2 = get_intern_input_link(link);
......
258 223
    return graph->link_filter->inputs[link->srcpad];
259 224
}
260 225

  
261
static int *graph_out_query_formats(AVFilterLink *link)
262
{
263
    AVFilterLink *link2 = get_intern_output_link(link);
264

  
265
    if(!link2)
266
        return avfilter_make_format_list(0);
267
    if(!link2->src->output_pads[link2->srcpad].query_formats)
268
        return avfilter_default_query_output_formats(link2);
269
    return link2->src->output_pads[link2->srcpad].query_formats(link2);
270
}
271

  
272 226
static int graph_out_request_frame(AVFilterLink *link)
273 227
{
274 228
    AVFilterLink *link2 = get_intern_output_link(link);
......
315 269
        .end_frame        = graph_in_end_frame,
316 270
        .get_video_buffer = graph_in_get_video_buffer,
317 271
        .draw_slice       = graph_in_draw_slice,
318
        .query_formats    = graph_in_query_formats,
319 272
        .config_props     = graph_in_config_props,
320 273
        /* XXX */
321 274
    };
......
323 276
    {
324 277
        .name          = NULL,          /* FIXME? */
325 278
        .type          = AV_PAD_VIDEO,
326
        .query_formats = link_in_query_formats,
327 279
        .request_frame = link_in_request_frame,
328 280
        .config_props  = link_in_config_props,
329 281
    };
......
345 297
        .name             = name,
346 298
        .type             = AV_PAD_VIDEO,
347 299
        .request_frame    = graph_out_request_frame,
348
        .query_formats    = graph_out_query_formats,
349 300
        .config_props     = graph_out_config_props,
350 301
    };
351 302
    AVFilterPad dummy_inpad =
......
356 307
        .end_frame        = link_out_end_frame,
357 308
        .draw_slice       = link_out_draw_slice,
358 309
        .get_video_buffer = link_out_get_video_buffer,
359
        .query_formats    = link_out_query_formats,
360 310
        .config_props     = link_out_config_props,
361 311
    };
362 312

  
......
406 356
    return NULL;
407 357
}
408 358

  
359
static int query_formats(AVFilterContext *graphctx)
360
{
361
    GraphContext *graph = graphctx->priv;
362
    AVFilterContext *linkfilt = graph->link_filter;
363
    int i, j;
364

  
365
    /* ask all the sub-filters for their supported colorspaces */
366
    for(i = 0; i < graph->filter_count; i ++) {
367
        if(graph->filters[i]->filter->query_formats)
368
            graph->filters[i]->filter->query_formats(graph->filters[i]);
369
        else
370
            avfilter_default_query_formats(graph->filters[i]);
371
    }
372

  
373
    /* use these formats on our exported links */
374
    for(i = 0; i < linkfilt->input_count; i ++) {
375
        avfilter_formats_ref( linkfilt->inputs[i]->in_formats,
376
                             &linkfilt->inputs[i]->out_formats);
377

  
378
        if(graphctx->outputs[i])
379
            avfilter_formats_ref( linkfilt-> inputs[i]->in_formats,
380
                                 &graphctx->outputs[i]->in_formats);
381
    }
382
    for(i = 0; i < linkfilt->output_count; i ++) {
383
        avfilter_formats_ref( linkfilt->outputs[i]->out_formats,
384
                             &linkfilt->outputs[i]->in_formats);
385

  
386
        if(graphctx->inputs[i])
387
            avfilter_formats_ref( linkfilt->outputs[i]->out_formats,
388
                                 &graphctx-> inputs[i]->out_formats);
389
    }
390

  
391
    /* go through and merge as many format lists as possible */
392
    for(i = 0; i < graph->filter_count; i ++) {
393
        AVFilterContext *filter = graph->filters[i];
394

  
395
        for(j = 0; j < filter->input_count; j ++) {
396
            AVFilterLink *link;
397
            if(!(link = filter->inputs[j]))
398
                continue;
399
            if(link->in_formats != link->out_formats) {
400
                if(!avfilter_merge_formats(link->in_formats,
401
                                           link->out_formats)) {
402
                    /* couldn't merge format lists. auto-insert scale filter */
403
                    AVFilterContext *scale;
404

  
405
                    if(!(scale = avfilter_open(&avfilter_vf_scale, NULL)))
406
                        return -1;
407
                    if(scale->filter->init(scale, NULL, NULL) ||
408
                       avfilter_insert_filter(link, scale, 0, 0)) {
409
                        avfilter_destroy(scale);
410
                        return -1;
411
                    }
412

  
413
                    avfilter_graph_add_filter(graphctx, scale);
414
                    scale->filter->query_formats(scale);
415
                    if(avfilter_merge_formats(scale-> inputs[0]->in_formats,
416
                                              scale-> inputs[0]->out_formats) ||
417
                       avfilter_merge_formats(scale->outputs[0]->in_formats,
418
                                              scale->outputs[0]->out_formats))
419
                        return -1;
420
                }
421
            }
422
        }
423
    }
424

  
425
    return 0;
426
}
427

  
428
static void pick_format(AVFilterLink *link)
429
{
430
    if(!link || !link->in_formats)
431
        return;
432

  
433
    link->in_formats->format_count = 1;
434
    link->format = link->in_formats->formats[0];
435

  
436
    avfilter_formats_unref(&link->in_formats);
437
    avfilter_formats_unref(&link->out_formats);
438
}
439

  
440
static void pick_formats(GraphContext *graph)
441
{
442
    int i, j;
443

  
444
    for(i = 0; i < graph->filter_count; i ++) {
445
        AVFilterContext *filter = graph->filters[i];
446

  
447
        if(filter->filter == &avfilter_vf_graph     ||
448
           filter->filter == &avfilter_vf_graphfile ||
449
           filter->filter == &avfilter_vf_graphdesc)
450
            pick_formats(filter->priv);
451

  
452
        for(j = 0; j < filter->input_count; j ++)
453
            pick_format(filter->inputs[j]);
454
        for(j = 0; j < filter->output_count; j ++)
455
            pick_format(filter->outputs[j]);
456
    }
457
}
458

  
459
int avfilter_graph_config_formats(AVFilterContext *graphctx)
460
{
461
    GraphContext *graph = graphctx->priv;
462

  
463
    /* Find supported formats from sub-filters, and merge along links */
464
    if(query_formats(graphctx))
465
        return -1;
466

  
467
    /* Once everything is merged, it's possible that we'll still have
468
     * multiple valid choices of colorspace. We pick the first one. */
469
    pick_formats(graph);
470

  
471
    return 0;
472
}
473

  
409 474
int avfilter_graph_config_links(AVFilterContext *graphctx)
410 475
{
411 476
    GraphContext *graph = graphctx->priv;
......
570 635
    .init      = init,
571 636
    .uninit    = uninit,
572 637

  
638
    .query_formats = query_formats,
639

  
573 640
    .inputs    = (AVFilterPad[]) {{ .name = NULL, }},
574 641
    .outputs   = (AVFilterPad[]) {{ .name = NULL, }},
575 642
};
......
667 734
    .init      = init_desc,
668 735
    .uninit    = uninit,
669 736

  
737
    .query_formats = query_formats,
738

  
670 739
    .inputs    = (AVFilterPad[]) {{ .name = NULL, }},
671 740
    .outputs   = (AVFilterPad[]) {{ .name = NULL, }},
672 741
};
......
696 765
    .init      = init_file,
697 766
    .uninit    = uninit,
698 767

  
768
    .query_formats = query_formats,
769

  
699 770
    .inputs    = (AVFilterPad[]) {{ .name = NULL, }},
700 771
    .outputs   = (AVFilterPad[]) {{ .name = NULL, }},
701 772
};

Also available in: Unified diff