History

lavfi: check the validity of formats lists.

Part of the code expects valid lists, in particular no duplicates. These tests allow to catch bugs in filters (unlikely but possible) and to give a clear message when the error comes from the user ((a)formats) or the application (buffersink). If we decide to switch to a more efficient merging algorithm, possibly sorting the lists, these functions will be the preferred place for pre-processing, and can be renamed accordingly.

Nicolas George committed 6 years ago

Commit 69f5f6e1 parent 6479f403 files · +148 −0Browse files

Unified · Split

3 files
  1. libavfilter/avfiltergraph.c +50 −0
  2. libavfilter/formats.c +70 −0
  3. libavfilter/formats.h +28 −0
libavfilter/avfiltergraph.c+50−0
@@ -313,6 +313,53 @@ static void sanitize_channel_layouts(void *log, AVFilterChannelLayouts *l) · 312 unmodified lines
313 }313 }
314}314}
315 315
316static int filter_link_check_formats(void *log, AVFilterLink *link, AVFilterFormatsConfig *cfg)
317{
318 int ret;
319
320 switch (link->type) {
321
322 case AVMEDIA_TYPE_VIDEO:
323 if ((ret = ff_formats_check_pixel_formats(log, cfg->formats)) < 0)
324 return ret;
325 break;
326
327 case AVMEDIA_TYPE_AUDIO:
328 if ((ret = ff_formats_check_sample_formats(log, cfg->formats)) < 0 ||
329 (ret = ff_formats_check_sample_rates(log, cfg->samplerates)) < 0 ||
330 (ret = ff_formats_check_channel_layouts(log, cfg->channel_layouts)) < 0)
331 return ret;
332 break;
333
334 default:
335 av_assert0(!"reached");
336 }
337 return 0;
338}
339
340/**
341 * Check the validity of the formats / etc. lists set by query_formats().
342 *
343 * In particular, check they do not contain any redundant element.
344 */
345static int filter_check_formats(AVFilterContext *ctx)
346{
347 unsigned i;
348 int ret;
349
350 for (i = 0; i < ctx->nb_inputs; i++) {
351 ret = filter_link_check_formats(ctx, ctx->inputs[i], &ctx->inputs[i]->outcfg);
352 if (ret < 0)
353 return ret;
354 }
355 for (i = 0; i < ctx->nb_outputs; i++) {
356 ret = filter_link_check_formats(ctx, ctx->outputs[i], &ctx->outputs[i]->incfg);
357 if (ret < 0)
358 return ret;
359 }
360 return 0;
361}
362
316static int filter_query_formats(AVFilterContext *ctx)363static int filter_query_formats(AVFilterContext *ctx)
317{364{
318 int ret, i;365 int ret, i;
@@ -329,6 +376,9 @@ static int filter_query_formats(AVFilterContext *ctx) · 10 unmodified lines
329 ctx->name, av_err2str(ret));376 ctx->name, av_err2str(ret));
330 return ret;377 return ret;
331 }378 }
379 ret = filter_check_formats(ctx);
380 if (ret < 0)
381 return ret;
332 382
333 for (i = 0; i < ctx->nb_inputs; i++)383 for (i = 0; i < ctx->nb_inputs; i++)
334 sanitize_channel_layouts(ctx, ctx->inputs[i]->outcfg.channel_layouts);384 sanitize_channel_layouts(ctx, ctx->inputs[i]->outcfg.channel_layouts);
libavfilter/formats.c+70−0
@@ -662,3 +662,73 @@ int ff_parse_channel_layout(int64_t *ret, int *nret, const char *arg, · 661 unmodified lines
662 662
663 return 0;663 return 0;
664}664}
665
666static int check_list(void *log, const char *name, const AVFilterFormats *fmts)
667{
668 unsigned i, j;
669
670 if (!fmts)
671 return 0;
672 if (!fmts->nb_formats) {
673 av_log(log, AV_LOG_ERROR, "Empty %s list\n", name);
674 return AVERROR(EINVAL);
675 }
676 for (i = 0; i < fmts->nb_formats; i++) {
677 for (j = i + 1; j < fmts->nb_formats; j++) {
678 if (fmts->formats[i] == fmts->formats[j]) {
679 av_log(log, AV_LOG_ERROR, "Duplicated %s\n", name);
680 return AVERROR(EINVAL);
681 }
682 }
683 }
684 return 0;
685}
686
687int ff_formats_check_pixel_formats(void *log, const AVFilterFormats *fmts)
688{
689 return check_list(log, "pixel format", fmts);
690}
691
692int ff_formats_check_sample_formats(void *log, const AVFilterFormats *fmts)
693{
694 return check_list(log, "sample format", fmts);
695}
696
697int ff_formats_check_sample_rates(void *log, const AVFilterFormats *fmts)
698{
699 if (!fmts || !fmts->nb_formats)
700 return 0;
701 return check_list(log, "sample rate", fmts);
702}
703
704static int layouts_compatible(uint64_t a, uint64_t b)
705{
706 return a == b ||
707 (KNOWN(a) && !KNOWN(b) && av_get_channel_layout_nb_channels(a) == FF_LAYOUT2COUNT(b)) ||
708 (KNOWN(b) && !KNOWN(a) && av_get_channel_layout_nb_channels(b) == FF_LAYOUT2COUNT(a));
709}
710
711int ff_formats_check_channel_layouts(void *log, const AVFilterChannelLayouts *fmts)
712{
713 unsigned i, j;
714
715 if (!fmts)
716 return 0;
717 if (fmts->all_layouts < fmts->all_counts) {
718 av_log(log, AV_LOG_ERROR, "Inconsistent generic list\n");
719 return AVERROR(EINVAL);
720 }
721 if (!fmts->all_layouts && !fmts->nb_channel_layouts) {
722 av_log(log, AV_LOG_ERROR, "Empty channel layout list\n");
723 return AVERROR(EINVAL);
724 }
725 for (i = 0; i < fmts->nb_channel_layouts; i++) {
726 for (j = i + 1; j < fmts->nb_channel_layouts; j++) {
727 if (layouts_compatible(fmts->channel_layouts[i], fmts->channel_layouts[j])) {
728 av_log(log, AV_LOG_ERROR, "Duplicated or redundant channel layout\n");
729 return AVERROR(EINVAL);
730 }
731 }
732 }
733 return 0;
734}
libavfilter/formats.h+28−0
@@ -291,4 +291,32 @@ void ff_formats_unref(AVFilterFormats **ref); · 290 unmodified lines
291 */291 */
292void ff_formats_changeref(AVFilterFormats **oldref, AVFilterFormats **newref);292void ff_formats_changeref(AVFilterFormats **oldref, AVFilterFormats **newref);
293 293
294/**
295 * Check that fmts is a valid pixel formats list.
296 *
297 * In particular, check for duplicates.
298 */
299int ff_formats_check_pixel_formats(void *log, const AVFilterFormats *fmts);
300
301/**
302 * Check that fmts is a valid sample formats list.
303 *
304 * In particular, check for duplicates.
305 */
306int ff_formats_check_sample_formats(void *log, const AVFilterFormats *fmts);
307
308/**
309 * Check that fmts is a valid sample rates list.
310 *
311 * In particular, check for duplicates.
312 */
313int ff_formats_check_sample_rates(void *log, const AVFilterFormats *fmts);
314
315/**
316 * Check that fmts is a valid channel layouts list.
317 *
318 * In particular, check for duplicates.
319 */
320int ff_formats_check_channel_layouts(void *log, const AVFilterChannelLayouts *fmts);
321
294#endif /* AVFILTER_FORMATS_H */322#endif /* AVFILTER_FORMATS_H */

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