avfiltergraph.c 5.94 KB
Newer Older
1
/*
2
 * filter graphs
3
 * copyright (c) 2008 Vitor Sessak
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 * copyright (c) 2007 Bobby Bingham
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

23 24 25
#include <ctype.h>
#include <string.h>

26 27 28
#include "avfilter.h"
#include "avfiltergraph.h"

29
void avfilter_graph_destroy(AVFilterGraph *graph)
Vitor Sessak's avatar
Vitor Sessak committed
30
{
31 32
    for(; graph->filter_count > 0; graph->filter_count --)
        avfilter_destroy(graph->filters[graph->filter_count - 1]);
33
    av_freep(&graph->scale_sws_opts);
34 35 36
    av_freep(&graph->filters);
}

Vitor Sessak's avatar
Vitor Sessak committed
37
int avfilter_graph_add_filter(AVFilterGraph *graph, AVFilterContext *filter)
38
{
39 40
    graph->filters = av_realloc(graph->filters,
                                sizeof(AVFilterContext*) * ++graph->filter_count);
Vitor Sessak's avatar
Vitor Sessak committed
41 42 43 44

    if (!graph->filters)
        return -1;

45
    graph->filters[graph->filter_count - 1] = filter;
Vitor Sessak's avatar
Vitor Sessak committed
46 47

    return 0;
48 49
}

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
int avfilter_graph_check_validity(AVFilterGraph *graph, AVClass *log_ctx)
{
    AVFilterContext *filt;
    int i, j;

    for (i=0; i < graph->filter_count; i++) {
        filt = graph->filters[i];

        for (j = 0; j < filt->input_count; j++) {
            if (!filt->inputs[j] || !filt->inputs[j]->src) {
                av_log(log_ctx, AV_LOG_ERROR,
                       "Input pad \"%s\" for the filter \"%s\" of type \"%s\" not connected to any source\n",
                       filt->input_pads[j].name, filt->name, filt->filter->name);
                return -1;
            }
        }

        for (j = 0; j < filt->output_count; j++) {
            if (!filt->outputs[j] || !filt->outputs[j]->dst) {
                av_log(log_ctx, AV_LOG_ERROR,
                       "Output pad \"%s\" for the filter \"%s\" of type \"%s\" not connected to any destination\n",
                       filt->output_pads[j].name, filt->name, filt->filter->name);
                return -1;
            }
        }
    }

    return 0;
}

80
AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name)
81 82 83 84 85 86 87 88 89 90
{
    int i;

    for(i = 0; i < graph->filter_count; i ++)
        if(graph->filters[i]->name && !strcmp(name, graph->filters[i]->name))
            return graph->filters[i];

    return NULL;
}

91
static int query_formats(AVFilterGraph *graph)
Vitor Sessak's avatar
Vitor Sessak committed
92 93
{
    int i, j;
94 95
    int scaler_count = 0;
    char inst_name[30];
Vitor Sessak's avatar
Vitor Sessak committed
96 97 98 99 100 101 102 103 104 105 106 107 108 109

    /* 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 ++) {
Vitor Sessak's avatar
Vitor Sessak committed
110 111
            AVFilterLink *link = filter->inputs[j];
            if(link && link->in_formats != link->out_formats) {
Vitor Sessak's avatar
Vitor Sessak committed
112 113
                if(!avfilter_merge_formats(link->in_formats,
                                           link->out_formats)) {
114
                    AVFilterContext *scale;
115
                    char scale_args[256];
Vitor Sessak's avatar
Vitor Sessak committed
116
                    /* couldn't merge format lists. auto-insert scale filter */
117
                    snprintf(inst_name, sizeof(inst_name), "auto-inserted scaler %d",
118 119 120
                             scaler_count);
                    scale =
                        avfilter_open(avfilter_get_by_name("scale"),inst_name);
Vitor Sessak's avatar
Vitor Sessak committed
121

122 123
                    snprintf(scale_args, sizeof(scale_args), "0:0:%s", graph->scale_sws_opts);
                    if(!scale || scale->filter->init(scale, scale_args, NULL) ||
Vitor Sessak's avatar
Vitor Sessak committed
124
                                 avfilter_insert_filter(link, scale, 0, 0)) {
Vitor Sessak's avatar
Vitor Sessak committed
125 126 127 128
                        avfilter_destroy(scale);
                        return -1;
                    }

Vitor Sessak's avatar
Vitor Sessak committed
129 130 131
                    if (avfilter_graph_add_filter(graph, scale) < 0)
                        return -1;

Vitor Sessak's avatar
Vitor Sessak committed
132
                    scale->filter->query_formats(scale);
Vitor Sessak's avatar
10l  
Vitor Sessak committed
133
                    if(!avfilter_merge_formats(scale-> inputs[0]->in_formats,
Vitor Sessak's avatar
Vitor Sessak committed
134
                                               scale-> inputs[0]->out_formats)||
Vitor Sessak's avatar
10l  
Vitor Sessak committed
135
                       !avfilter_merge_formats(scale->outputs[0]->in_formats,
Vitor Sessak's avatar
Vitor Sessak committed
136
                                               scale->outputs[0]->out_formats))
Vitor Sessak's avatar
Vitor Sessak committed
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
                        return -1;
                }
            }
        }
    }

    return 0;
}

static void pick_format(AVFilterLink *link)
{
    if(!link || !link->in_formats)
        return;

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

    avfilter_formats_unref(&link->in_formats);
    avfilter_formats_unref(&link->out_formats);
}

158
static void pick_formats(AVFilterGraph *graph)
Vitor Sessak's avatar
Vitor Sessak committed
159 160 161 162 163 164 165 166 167 168 169 170 171
{
    int i, j;

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

        for(j = 0; j < filter->input_count; j ++)
            pick_format(filter->inputs[j]);
        for(j = 0; j < filter->output_count; j ++)
            pick_format(filter->outputs[j]);
    }
}

172
int avfilter_graph_config_formats(AVFilterGraph *graph)
Vitor Sessak's avatar
Vitor Sessak committed
173
{
174
    /* find supported formats from sub-filters, and merge along links */
Vitor Sessak's avatar
Vitor Sessak committed
175
    if(query_formats(graph))
Vitor Sessak's avatar
Vitor Sessak committed
176 177 178
        return -1;

    /* Once everything is merged, it's possible that we'll still have
Vitor Sessak's avatar
Vitor Sessak committed
179
     * multiple valid colorspace choices. We pick the first one. */
Vitor Sessak's avatar
Vitor Sessak committed
180 181 182 183 184
    pick_formats(graph);

    return 0;
}