History

avfilter/avfiltergraph: add logging for filter formats

There is no convenient way, from the command line, to figure out which formats a filter actually supports. This commit changes that by adding a log output, at debug level, to simply print the list of formats each filter advertises on its links, before any negotiation. Furthermore, we can use the exact same helper function to also print out the corresponding filter links when there is an error during format negotiation. We need to use AV_BRINT_SIZE_UNLIMITED because the default format list for filters like vf_scale is about 1700 characters long, significantly larger than the the 1 kB default buffer.

Niklas Haas committed 1 year ago

Commit 03b91801 parent 1a61db91 file · +63 −1Browse files

Unified · Split

libavfilter/avfiltergraph.c+63−1
@@ -440,6 +440,62 @@ static int formats_declared(AVFilterContext *f) · 439 unmodified lines
440 return 1;440 return 1;
441}441}
442 442
443static void print_formats(void *log_ctx, int level, enum AVMediaType type,
444 const AVFilterFormats *formats)
445{
446 AVBPrint bp;
447 av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
448
449 switch (type) {
450 case AVMEDIA_TYPE_VIDEO:
451 for (unsigned i = 0; i < formats->nb_formats; i++)
452 av_bprintf(&bp, "%s%s", bp.len ? " " : "", av_get_pix_fmt_name(formats->formats[i]));
453 break;
454 case AVMEDIA_TYPE_AUDIO:
455 for (unsigned i = 0; i < formats->nb_formats; i++)
456 av_bprintf(&bp, "%s%s", bp.len ? " " : "", av_get_sample_fmt_name(formats->formats[i]));
457 break;
458 default:
459 av_bprintf(&bp, "(unknown)");
460 break;
461 }
462
463 if (av_bprint_is_complete(&bp)) {
464 av_log(log_ctx, level, "%s\n", bp.str);
465 } else {
466 av_log(log_ctx, level, "(out of memory)\n");
467 }
468 av_bprint_finalize(&bp, NULL);
469}
470
471static void print_link_formats(void *log_ctx, int level, const AVFilterLink *l)
472{
473 if (av_log_get_level() < level)
474 return;
475
476 av_log(log_ctx, level, "Link '%s.%s' -> '%s.%s':\n"
477 " src: ", l->src->name, l->srcpad->name, l->dst->name, l->dstpad->name);
478 print_formats(log_ctx, level, l->type, l->incfg.formats);
479 av_log(log_ctx, level, " dst: ");
480 print_formats(log_ctx, level, l->type, l->outcfg.formats);
481}
482
483static void print_filter_formats(void *log_ctx, int level, const AVFilterContext *f)
484{
485 if (av_log_get_level() < level)
486 return;
487
488 av_log(log_ctx, level, "Filter '%s' formats:\n", f->name);
489 for (int i = 0; i < f->nb_inputs; i++) {
490 av_log(log_ctx, level, " in[%d] '%s': ", i, f->input_pads[i].name);
491 print_formats(log_ctx, level, f->inputs[i]->type, f->inputs[i]->outcfg.formats);
492 }
493 for (int i = 0; i < f->nb_outputs; i++) {
494 av_log(log_ctx, level, " out[%d] '%s': ", i, f->output_pads[i].name);
495 print_formats(log_ctx, level, f->outputs[i]->type, f->outputs[i]->incfg.formats);
496 }
497}
498
443/**499/**
444 * Perform one round of query_formats() and merging formats lists on the500 * Perform one round of query_formats() and merging formats lists on the
445 * filter graph.501 * filter graph.
@@ -467,7 +523,10 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx) · 21 unmodified lines
467 if (ret < 0 && ret != AVERROR(EAGAIN))523 if (ret < 0 && ret != AVERROR(EAGAIN))
468 return ret;524 return ret;
469 /* note: EAGAIN could indicate a partial success, not counted yet */525 /* note: EAGAIN could indicate a partial success, not counted yet */
470 count_queried += ret >= 0;526 if (ret >= 0) {
527 print_filter_formats(log_ctx, AV_LOG_DEBUG, f);
528 count_queried++;
529 }
471 }530 }
472 531
473 /* go through and merge as many format lists as possible */532 /* go through and merge as many format lists as possible */
@@ -524,6 +583,7 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx) · 50 unmodified lines
524 "The filters '%s' and '%s' do not have a common format "583 "The filters '%s' and '%s' do not have a common format "
525 "and automatic conversion is disabled.\n",584 "and automatic conversion is disabled.\n",
526 link->src->name, link->dst->name);585 link->src->name, link->dst->name);
586 print_link_formats(log_ctx, AV_LOG_ERROR, link);
527 return AVERROR(EINVAL);587 return AVERROR(EINVAL);
528 }588 }
529 589
@@ -532,6 +592,7 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx) · 2 unmodified lines
532 av_log(log_ctx, AV_LOG_ERROR,592 av_log(log_ctx, AV_LOG_ERROR,
533 "'%s' filter not present, cannot convert formats.\n",593 "'%s' filter not present, cannot convert formats.\n",
534 neg->conversion_filter);594 neg->conversion_filter);
595 print_link_formats(log_ctx, AV_LOG_ERROR, link);
535 return AVERROR(EINVAL);596 return AVERROR(EINVAL);
536 }597 }
537 snprintf(inst_name, sizeof(inst_name), "auto_%s_%d",598 snprintf(inst_name, sizeof(inst_name), "auto_%s_%d",
@@ -583,6 +644,7 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx) · 45 unmodified lines
583 av_log(log_ctx, AV_LOG_ERROR,644 av_log(log_ctx, AV_LOG_ERROR,
584 "Impossible to convert between the formats supported by the filter "645 "Impossible to convert between the formats supported by the filter "
585 "'%s' and the filter '%s'\n", link->src->name, link->dst->name);646 "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
647 print_link_formats(log_ctx, AV_LOG_ERROR, link);
586 return AVERROR(ENOSYS);648 return AVERROR(ENOSYS);
587 }649 }
588 }650 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t