Originally committed as revision 12734 to svn://svn.ffmpeg.org/ffmpeg/trunk
| ... | ... |
@@ -22,93 +22,39 @@ |
| 22 | 22 |
#include "avfilter.h" |
| 23 | 23 |
#include "avfiltergraph.h" |
| 24 | 24 |
|
| 25 |
-typedef struct AVFilterGraph {
|
|
| 26 |
- unsigned filter_count; |
|
| 27 |
- AVFilterContext **filters; |
|
| 28 |
- |
|
| 29 |
- /** fake filters to handle links to internal filters */ |
|
| 30 |
- AVFilterContext *link_filter_in; |
|
| 31 |
- AVFilterContext *link_filter_out; |
|
| 32 |
-} GraphContext; |
|
| 33 |
- |
|
| 34 |
-typedef struct {
|
|
| 35 |
- AVFilterContext *graph; |
|
| 36 |
-} GraphLinkContext; |
|
| 37 |
- |
|
| 38 |
-static int link_init(AVFilterContext *ctx, const char *args, void *opaque) |
|
| 39 |
-{
|
|
| 40 |
- GraphLinkContext *linkctx = ctx->priv; |
|
| 41 |
- linkctx->graph = opaque; |
|
| 42 |
- return !opaque; |
|
| 43 |
-} |
|
| 44 |
- |
|
| 45 | 25 |
/** |
| 46 |
- * Given the link between the dummy filter and an internal filter whose input |
|
| 47 |
- * is being exported outside the graph, this returns the externally visible |
|
| 48 |
- * link. |
|
| 26 |
+ * For use in av_log |
|
| 49 | 27 |
*/ |
| 50 |
-static inline AVFilterLink *get_extern_input_link(AVFilterLink *link) |
|
| 28 |
+static const char *log_name(void *p) |
|
| 51 | 29 |
{
|
| 52 |
- GraphLinkContext *lctx = link->src->priv; |
|
| 53 |
- return lctx->graph->inputs[link->srcpad]; |
|
| 30 |
+ return "Filter parser"; |
|
| 54 | 31 |
} |
| 55 | 32 |
|
| 56 |
-/** |
|
| 57 |
- * Given the link between the dummy filter and an internal filter whose output |
|
| 58 |
- * is being exported outside the graph, this returns the externally visible |
|
| 59 |
- * link. |
|
| 60 |
- */ |
|
| 61 |
-static inline AVFilterLink *get_extern_output_link(AVFilterLink *link) |
|
| 62 |
-{
|
|
| 63 |
- GraphLinkContext *lctx = link->dst->priv; |
|
| 64 |
- return lctx->graph->outputs[link->dstpad]; |
|
| 65 |
-} |
|
| 66 |
- |
|
| 67 |
- |
|
| 68 |
-/** dummy filter used to help export filters pads outside the graph */ |
|
| 69 |
-static AVFilter vf_graph_dummy = |
|
| 70 |
-{
|
|
| 71 |
- .name = "graph_dummy", |
|
| 72 |
- |
|
| 73 |
- .priv_size = sizeof(GraphLinkContext), |
|
| 74 |
- |
|
| 75 |
- .init = link_init, |
|
| 76 |
- |
|
| 77 |
- .inputs = (AVFilterPad[]) {{ .name = NULL, }},
|
|
| 78 |
- .outputs = (AVFilterPad[]) {{ .name = NULL, }},
|
|
| 33 |
+static const AVClass filter_parser_class = {
|
|
| 34 |
+ "Filter parser", |
|
| 35 |
+ log_name |
|
| 79 | 36 |
}; |
| 80 | 37 |
|
| 81 |
-static void uninit(AVFilterContext *ctx) |
|
| 82 |
-{
|
|
| 83 |
- GraphContext *graph = ctx->priv; |
|
| 38 |
+static const AVClass *log_ctx = &filter_parser_class; |
|
| 84 | 39 |
|
| 85 |
- if(graph->link_filter_in) {
|
|
| 86 |
- avfilter_destroy(graph->link_filter_in); |
|
| 87 |
- graph->link_filter_in = NULL; |
|
| 88 |
- } |
|
| 89 |
- if(graph->link_filter_out) {
|
|
| 90 |
- avfilter_destroy(graph->link_filter_out); |
|
| 91 |
- graph->link_filter_out = NULL; |
|
| 92 |
- } |
|
| 40 |
+static void uninit(GraphContext *graph) |
|
| 41 |
+{
|
|
| 93 | 42 |
for(; graph->filter_count > 0; graph->filter_count --) |
| 94 | 43 |
avfilter_destroy(graph->filters[graph->filter_count - 1]); |
| 95 | 44 |
av_freep(&graph->filters); |
| 96 | 45 |
} |
| 97 | 46 |
|
| 98 | 47 |
/* TODO: insert in sorted order */ |
| 99 |
-void avfilter_graph_add_filter(AVFilterContext *graphctx, AVFilterContext *filter) |
|
| 48 |
+void avfilter_graph_add_filter(GraphContext *graph, AVFilterContext *filter) |
|
| 100 | 49 |
{
|
| 101 |
- GraphContext *graph = graphctx->priv; |
|
| 102 |
- |
|
| 103 | 50 |
graph->filters = av_realloc(graph->filters, |
| 104 | 51 |
sizeof(AVFilterContext*) * ++graph->filter_count); |
| 105 | 52 |
graph->filters[graph->filter_count - 1] = filter; |
| 106 | 53 |
} |
| 107 | 54 |
|
| 108 | 55 |
/* search intelligently, once we insert in order */ |
| 109 |
-AVFilterContext *avfilter_graph_get_filter(AVFilterContext *ctx, char *name) |
|
| 56 |
+AVFilterContext *avfilter_graph_get_filter(GraphContext *graph, char *name) |
|
| 110 | 57 |
{
|
| 111 |
- GraphContext *graph = ctx->priv; |
|
| 112 | 58 |
int i; |
| 113 | 59 |
|
| 114 | 60 |
if(!name) |
| ... | ... |
@@ -121,11 +67,8 @@ AVFilterContext *avfilter_graph_get_filter(AVFilterContext *ctx, char *name) |
| 121 | 121 |
return NULL; |
| 122 | 122 |
} |
| 123 | 123 |
|
| 124 |
-static int query_formats(AVFilterContext *graphctx) |
|
| 124 |
+static int query_formats(GraphContext *graph) |
|
| 125 | 125 |
{
|
| 126 |
- GraphContext *graph = graphctx->priv; |
|
| 127 |
- AVFilterContext *linkfiltin = graph->link_filter_in; |
|
| 128 |
- AVFilterContext *linkfiltout = graph->link_filter_out; |
|
| 129 | 126 |
int i, j; |
| 130 | 127 |
|
| 131 | 128 |
/* ask all the sub-filters for their supported colorspaces */ |
| ... | ... |
@@ -136,24 +79,6 @@ static int query_formats(AVFilterContext *graphctx) |
| 136 | 136 |
avfilter_default_query_formats(graph->filters[i]); |
| 137 | 137 |
} |
| 138 | 138 |
|
| 139 |
- /* use these formats on our exported links */ |
|
| 140 |
- for(i = 0; i < linkfiltout->input_count; i ++) {
|
|
| 141 |
- avfilter_formats_ref( linkfiltout->inputs[i]->in_formats, |
|
| 142 |
- &linkfiltout->inputs[i]->out_formats); |
|
| 143 |
- |
|
| 144 |
- if(graphctx->outputs[i]) |
|
| 145 |
- avfilter_formats_ref(linkfiltout->inputs[i]->in_formats, |
|
| 146 |
- &graphctx->outputs[i]->in_formats); |
|
| 147 |
- } |
|
| 148 |
- for(i = 0; i < linkfiltin->output_count; i ++) {
|
|
| 149 |
- avfilter_formats_ref( linkfiltin->outputs[i]->out_formats, |
|
| 150 |
- &linkfiltin->outputs[i]->in_formats); |
|
| 151 |
- |
|
| 152 |
- if(graphctx->inputs[i]) |
|
| 153 |
- avfilter_formats_ref(linkfiltin->outputs[i]->out_formats, |
|
| 154 |
- &graphctx-> inputs[i]->out_formats); |
|
| 155 |
- } |
|
| 156 |
- |
|
| 157 | 139 |
/* go through and merge as many format lists as possible */ |
| 158 | 140 |
for(i = 0; i < graph->filter_count; i ++) {
|
| 159 | 141 |
AVFilterContext *filter = graph->filters[i]; |
| ... | ... |
@@ -177,7 +102,7 @@ static int query_formats(AVFilterContext *graphctx) |
| 177 | 177 |
return -1; |
| 178 | 178 |
} |
| 179 | 179 |
|
| 180 |
- avfilter_graph_add_filter(graphctx, scale); |
|
| 180 |
+ avfilter_graph_add_filter(graph, scale); |
|
| 181 | 181 |
scale->filter->query_formats(scale); |
| 182 | 182 |
if(!avfilter_merge_formats(scale-> inputs[0]->in_formats, |
| 183 | 183 |
scale-> inputs[0]->out_formats) || |
| ... | ... |
@@ -211,9 +136,6 @@ static void pick_formats(GraphContext *graph) |
| 211 | 211 |
for(i = 0; i < graph->filter_count; i ++) {
|
| 212 | 212 |
AVFilterContext *filter = graph->filters[i]; |
| 213 | 213 |
|
| 214 |
- if(filter->filter == &avfilter_vf_graph) |
|
| 215 |
- pick_formats(filter->priv); |
|
| 216 |
- |
|
| 217 | 214 |
for(j = 0; j < filter->input_count; j ++) |
| 218 | 215 |
pick_format(filter->inputs[j]); |
| 219 | 216 |
for(j = 0; j < filter->output_count; j ++) |
| ... | ... |
@@ -221,12 +143,10 @@ static void pick_formats(GraphContext *graph) |
| 221 | 221 |
} |
| 222 | 222 |
} |
| 223 | 223 |
|
| 224 |
-int avfilter_graph_config_formats(AVFilterContext *graphctx) |
|
| 224 |
+int avfilter_graph_config_formats(GraphContext *graph) |
|
| 225 | 225 |
{
|
| 226 |
- GraphContext *graph = graphctx->priv; |
|
| 227 |
- |
|
| 228 | 226 |
/* find supported formats from sub-filters, and merge along links */ |
| 229 |
- if(query_formats(graphctx)) |
|
| 227 |
+ if(query_formats(graph)) |
|
| 230 | 228 |
return -1; |
| 231 | 229 |
|
| 232 | 230 |
/* Once everything is merged, it's possible that we'll still have |
| ... | ... |
@@ -236,7 +156,7 @@ int avfilter_graph_config_formats(AVFilterContext *graphctx) |
| 236 | 236 |
return 0; |
| 237 | 237 |
} |
| 238 | 238 |
|
| 239 |
-static int graph_load_from_desc2(AVFilterContext *ctx, AVFilterGraphDesc *desc) |
|
| 239 |
+static int graph_load_from_desc2(GraphContext *ctx, AVFilterGraphDesc *desc) |
|
| 240 | 240 |
{
|
| 241 | 241 |
AVFilterGraphDescFilter *curfilt; |
| 242 | 242 |
AVFilterGraphDescLink *curlink; |
| ... | ... |
@@ -250,13 +170,13 @@ static int graph_load_from_desc2(AVFilterContext *ctx, AVFilterGraphDesc *desc) |
| 250 | 250 |
snprintf(tmp, 20, "%d", curfilt->index); |
| 251 | 251 |
if(!(filterdef = avfilter_get_by_name(curfilt->filter)) || |
| 252 | 252 |
!(filt = avfilter_open(filterdef, tmp))) {
|
| 253 |
- av_log(ctx, AV_LOG_ERROR, |
|
| 253 |
+ av_log(&log_ctx, AV_LOG_ERROR, |
|
| 254 | 254 |
"error creating filter '%s'\n", curfilt->filter); |
| 255 | 255 |
goto fail; |
| 256 | 256 |
} |
| 257 | 257 |
avfilter_graph_add_filter(ctx, filt); |
| 258 | 258 |
if(avfilter_init_filter(filt, curfilt->args, NULL)) {
|
| 259 |
- av_log(ctx, AV_LOG_ERROR, |
|
| 259 |
+ av_log(&log_ctx, AV_LOG_ERROR, |
|
| 260 | 260 |
"error initializing filter '%s'\n", curfilt->filter); |
| 261 | 261 |
goto fail; |
| 262 | 262 |
} |
| ... | ... |
@@ -266,16 +186,16 @@ static int graph_load_from_desc2(AVFilterContext *ctx, AVFilterGraphDesc *desc) |
| 266 | 266 |
for(curlink = desc->links; curlink; curlink = curlink->next) {
|
| 267 | 267 |
snprintf(tmp, 20, "%d", curlink->src); |
| 268 | 268 |
if(!(filt = avfilter_graph_get_filter(ctx, tmp))) {
|
| 269 |
- av_log(ctx, AV_LOG_ERROR, "link source does not exist in graph\n"); |
|
| 269 |
+ av_log(&log_ctx, AV_LOG_ERROR, "link source does not exist in graph\n"); |
|
| 270 | 270 |
goto fail; |
| 271 | 271 |
} |
| 272 | 272 |
snprintf(tmp, 20, "%d", curlink->dst); |
| 273 | 273 |
if(!(filtb = avfilter_graph_get_filter(ctx, tmp))) {
|
| 274 |
- av_log(ctx, AV_LOG_ERROR, "link destination does not exist in graph\n"); |
|
| 274 |
+ av_log(&log_ctx, AV_LOG_ERROR, "link destination does not exist in graph\n"); |
|
| 275 | 275 |
goto fail; |
| 276 | 276 |
} |
| 277 | 277 |
if(avfilter_link(filt, curlink->srcpad, filtb, curlink->dstpad)) {
|
| 278 |
- av_log(ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n"); |
|
| 278 |
+ av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n"); |
|
| 279 | 279 |
goto fail; |
| 280 | 280 |
} |
| 281 | 281 |
} |
| ... | ... |
@@ -287,24 +207,24 @@ fail: |
| 287 | 287 |
return -1; |
| 288 | 288 |
} |
| 289 | 289 |
|
| 290 |
-int graph_load_from_desc3(AVFilterContext *ctx, AVFilterGraphDesc *desc, AVFilterContext *in, int inpad, AVFilterContext *out, int outpad) |
|
| 290 |
+int graph_load_from_desc3(GraphContext *graph, AVFilterGraphDesc *desc, AVFilterContext *in, int inpad, AVFilterContext *out, int outpad) |
|
| 291 | 291 |
{
|
| 292 | 292 |
AVFilterGraphDescExport *curpad; |
| 293 | 293 |
char tmp[20]; |
| 294 | 294 |
AVFilterContext *filt; |
| 295 | 295 |
|
| 296 |
- if (graph_load_from_desc2(ctx, desc) < 0) |
|
| 296 |
+ if (graph_load_from_desc2(graph, desc) < 0) |
|
| 297 | 297 |
goto fail; |
| 298 | 298 |
|
| 299 | 299 |
/* export all input pads */ |
| 300 | 300 |
for(curpad = desc->inputs; curpad; curpad = curpad->next) {
|
| 301 | 301 |
snprintf(tmp, 20, "%d", curpad->filter); |
| 302 |
- if(!(filt = avfilter_graph_get_filter(ctx, tmp))) {
|
|
| 303 |
- av_log(ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n"); |
|
| 302 |
+ if(!(filt = avfilter_graph_get_filter(graph, tmp))) {
|
|
| 303 |
+ av_log(&log_ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n"); |
|
| 304 | 304 |
goto fail; |
| 305 | 305 |
} |
| 306 | 306 |
if(avfilter_link(in, inpad, filt, curpad->pad)) {
|
| 307 |
- av_log(ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n"); |
|
| 307 |
+ av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n"); |
|
| 308 | 308 |
goto fail; |
| 309 | 309 |
} |
| 310 | 310 |
} |
| ... | ... |
@@ -312,13 +232,13 @@ int graph_load_from_desc3(AVFilterContext *ctx, AVFilterGraphDesc *desc, AVFilte |
| 312 | 312 |
/* export all output pads */ |
| 313 | 313 |
for(curpad = desc->outputs; curpad; curpad = curpad->next) {
|
| 314 | 314 |
snprintf(tmp, 20, "%d", curpad->filter); |
| 315 |
- if(!(filt = avfilter_graph_get_filter(ctx, tmp))) {
|
|
| 316 |
- av_log(ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n"); |
|
| 315 |
+ if(!(filt = avfilter_graph_get_filter(graph, tmp))) {
|
|
| 316 |
+ av_log(&log_ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n"); |
|
| 317 | 317 |
goto fail; |
| 318 | 318 |
} |
| 319 | 319 |
|
| 320 | 320 |
if(avfilter_link(filt, curpad->pad, out, outpad)) {
|
| 321 |
- av_log(ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n"); |
|
| 321 |
+ av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n"); |
|
| 322 | 322 |
goto fail; |
| 323 | 323 |
} |
| 324 | 324 |
} |
| ... | ... |
@@ -326,44 +246,6 @@ int graph_load_from_desc3(AVFilterContext *ctx, AVFilterGraphDesc *desc, AVFilte |
| 326 | 326 |
return 0; |
| 327 | 327 |
|
| 328 | 328 |
fail: |
| 329 |
- uninit(ctx); |
|
| 330 |
- return -1; |
|
| 331 |
-} |
|
| 332 |
- |
|
| 333 |
-static int init(AVFilterContext *ctx, const char *args, void *opaque) |
|
| 334 |
-{
|
|
| 335 |
- GraphContext *gctx = ctx->priv; |
|
| 336 |
- |
|
| 337 |
- if(!(gctx->link_filter_in = avfilter_open(&vf_graph_dummy, NULL))) |
|
| 338 |
- return -1; |
|
| 339 |
- if(avfilter_init_filter(gctx->link_filter_in, NULL, ctx)) |
|
| 340 |
- goto fail; |
|
| 341 |
- if(!(gctx->link_filter_out = avfilter_open(&vf_graph_dummy, NULL))) |
|
| 342 |
- goto fail; |
|
| 343 |
- if(avfilter_init_filter(gctx->link_filter_out, NULL, ctx)) |
|
| 344 |
- goto fail; |
|
| 345 |
- |
|
| 346 |
- return 0; |
|
| 347 |
- |
|
| 348 |
-fail: |
|
| 349 |
- avfilter_destroy(gctx->link_filter_in); |
|
| 350 |
- if(gctx->link_filter_out) |
|
| 351 |
- avfilter_destroy(gctx->link_filter_out); |
|
| 329 |
+ uninit(graph); |
|
| 352 | 330 |
return -1; |
| 353 | 331 |
} |
| 354 |
- |
|
| 355 |
-AVFilter avfilter_vf_graph = |
|
| 356 |
-{
|
|
| 357 |
- .name = "graph", |
|
| 358 |
- |
|
| 359 |
- .priv_size = sizeof(GraphContext), |
|
| 360 |
- |
|
| 361 |
- .init = init, |
|
| 362 |
- .uninit = uninit, |
|
| 363 |
- |
|
| 364 |
- .query_formats = query_formats, |
|
| 365 |
- |
|
| 366 |
- .inputs = (AVFilterPad[]) {{ .name = NULL, }},
|
|
| 367 |
- .outputs = (AVFilterPad[]) {{ .name = NULL, }},
|
|
| 368 |
-}; |
|
| 369 |
- |
| ... | ... |
@@ -66,7 +66,10 @@ typedef struct |
| 66 | 66 |
AVFilterGraphDescExport *outputs; ///< outputs to export |
| 67 | 67 |
} AVFilterGraphDesc; |
| 68 | 68 |
|
| 69 |
-extern AVFilter avfilter_vf_graph; |
|
| 69 |
+typedef struct AVFilterGraph {
|
|
| 70 |
+ unsigned filter_count; |
|
| 71 |
+ AVFilterContext **filters; |
|
| 72 |
+} GraphContext; |
|
| 70 | 73 |
|
| 71 | 74 |
/** |
| 72 | 75 |
* Parse a graph composed of a simple chain of filters which is described by |
| ... | ... |
@@ -87,20 +90,20 @@ void avfilter_graph_free_desc(AVFilterGraphDesc *desc); |
| 87 | 87 |
* @param graph The filter graph |
| 88 | 88 |
* @param filter The filter to be added |
| 89 | 89 |
*/ |
| 90 |
-void avfilter_graph_add_filter(AVFilterContext *graphctx, AVFilterContext *filter); |
|
| 90 |
+void avfilter_graph_add_filter(GraphContext *graphctx, AVFilterContext *filter); |
|
| 91 | 91 |
|
| 92 | 92 |
/** |
| 93 | 93 |
* Configure the formats of all the links in the graph. |
| 94 | 94 |
*/ |
| 95 |
-int avfilter_graph_config_formats(AVFilterContext *graphctx); |
|
| 95 |
+int avfilter_graph_config_formats(GraphContext *graphctx); |
|
| 96 | 96 |
|
| 97 | 97 |
/** |
| 98 | 98 |
* Configure the parameters (resolution, etc) of all links in the graph. |
| 99 | 99 |
*/ |
| 100 |
-int avfilter_graph_config_links(AVFilterContext *graphctx); |
|
| 100 |
+int avfilter_graph_config_links(GraphContext *graphctx); |
|
| 101 | 101 |
|
| 102 | 102 |
|
| 103 |
-int graph_load_from_desc3(AVFilterContext *ctx, AVFilterGraphDesc *desc, |
|
| 103 |
+int graph_load_from_desc3(GraphContext *ctx, AVFilterGraphDesc *desc, |
|
| 104 | 104 |
AVFilterContext *in, int inpad, |
| 105 | 105 |
AVFilterContext *out, int outpad); |
| 106 | 106 |
|