diff options
author | Nicolas George <george@nsup.org> | 2021-07-24 17:06:53 +0200 |
---|---|---|
committer | Nicolas George <george@nsup.org> | 2021-08-14 09:17:45 +0200 |
commit | 86d3dd5627b5c8c179aa48c7e4834a69371a14e6 (patch) | |
tree | 5287b075f7c97a7a9296a3d6898491a5d8768fa9 /libavfilter/formats.c | |
parent | 1d8e1afc009f2a916f672fc57f4971504bb13fb3 (diff) |
lavfi/formats: put merge functions in structures.
It makes the code clearer and will allow adding new stages
of negotiation easier.
Diffstat (limited to 'libavfilter/formats.c')
-rw-r--r-- | libavfilter/formats.c | 114 |
1 files changed, 102 insertions, 12 deletions
diff --git a/libavfilter/formats.c b/libavfilter/formats.c index 507ab51217..9ddd0e47ea 100644 --- a/libavfilter/formats.c +++ b/libavfilter/formats.c @@ -100,6 +100,8 @@ static int merge_formats_internal(AVFilterFormats *a, AVFilterFormats *b, int alpha1=0, alpha2=0; int chroma1=0, chroma2=0; + av_assert2(check || (a->refcount && b->refcount)); + if (a == b) return 1; @@ -132,43 +134,86 @@ static int merge_formats_internal(AVFilterFormats *a, AVFilterFormats *b, return 1; } -int ff_can_merge_formats(const AVFilterFormats *a, const AVFilterFormats *b, - enum AVMediaType type) + +/** + * Check the formats lists for compatibility for merging without actually + * merging. + * + * @return 1 if they are compatible, 0 if not. + */ +static int can_merge_pix_fmts(const void *a, const void *b) { return merge_formats_internal((AVFilterFormats *)a, - (AVFilterFormats *)b, type, 1); + (AVFilterFormats *)b, AVMEDIA_TYPE_VIDEO, 1); +} + +/** + * Merge the formats lists if they are compatible and update all the + * references of a and b to point to the combined list and free the old + * lists as needed. The combined list usually contains the intersection of + * the lists of a and b. + * + * Both a and b must have owners (i.e. refcount > 0) for these functions. + * + * @return 1 if merging succeeded, 0 if a and b are incompatible + * and negative AVERROR code on failure. + * a and b are unmodified if 0 is returned. + */ +static int merge_pix_fmts(void *a, void *b) +{ + return merge_formats_internal(a, b, AVMEDIA_TYPE_VIDEO, 0); } -int ff_merge_formats(AVFilterFormats *a, AVFilterFormats *b, - enum AVMediaType type) +/** + * See can_merge_pix_fmts(). + */ +static int can_merge_sample_fmts(const void *a, const void *b) { - av_assert2(a->refcount && b->refcount); - return merge_formats_internal(a, b, type, 0); + return merge_formats_internal((AVFilterFormats *)a, + (AVFilterFormats *)b, AVMEDIA_TYPE_AUDIO, 1); +} + +/** + * See merge_pix_fmts(). + */ +static int merge_sample_fmts(void *a, void *b) +{ + return merge_formats_internal(a, b, AVMEDIA_TYPE_AUDIO, 0); } static int merge_samplerates_internal(AVFilterFormats *a, AVFilterFormats *b, int check) { + av_assert2(check || (a->refcount && b->refcount)); if (a == b) return 1; MERGE_FORMATS(a, b, formats, nb_formats, AVFilterFormats, check, 1); return 1; } -int ff_can_merge_samplerates(const AVFilterFormats *a, const AVFilterFormats *b) +/** + * See can_merge_pix_fmts(). + */ +static int can_merge_samplerates(const void *a, const void *b) { return merge_samplerates_internal((AVFilterFormats *)a, (AVFilterFormats *)b, 1); } -int ff_merge_samplerates(AVFilterFormats *a, AVFilterFormats *b) +/** + * See merge_pix_fmts(). + */ +static int merge_samplerates(void *a, void *b) { - av_assert2(a->refcount && b->refcount); return merge_samplerates_internal(a, b, 0); } -int ff_merge_channel_layouts(AVFilterChannelLayouts *a, - AVFilterChannelLayouts *b) +/** + * See merge_pix_fmts(). + */ +static int merge_channel_layouts(void *va, void *vb) { + AVFilterChannelLayouts *a = va; + AVFilterChannelLayouts *b = vb; uint64_t *channel_layouts; unsigned a_all = a->all_layouts + a->all_counts; unsigned b_all = b->all_layouts + b->all_counts; @@ -255,6 +300,51 @@ int ff_merge_channel_layouts(AVFilterChannelLayouts *a, return 1; } +static const AVFilterFormatsMerger mergers_video[] = { + { + .offset = offsetof(AVFilterFormatsConfig, formats), + .merge = merge_pix_fmts, + .can_merge = can_merge_pix_fmts, + }, +}; + +static const AVFilterFormatsMerger mergers_audio[] = { + { + .offset = offsetof(AVFilterFormatsConfig, channel_layouts), + .merge = merge_channel_layouts, + .can_merge = NULL, + }, + { + .offset = offsetof(AVFilterFormatsConfig, samplerates), + .merge = merge_samplerates, + .can_merge = can_merge_samplerates, + }, + { + .offset = offsetof(AVFilterFormatsConfig, formats), + .merge = merge_sample_fmts, + .can_merge = can_merge_sample_fmts, + }, +}; + +static const AVFilterNegotiation negotiate_video = { + .nb = FF_ARRAY_ELEMS(mergers_video), + .mergers = mergers_video, +}; + +static const AVFilterNegotiation negotiate_audio = { + .nb = FF_ARRAY_ELEMS(mergers_audio), + .mergers = mergers_audio, +}; + +const AVFilterNegotiation *ff_filter_get_negotiation(AVFilterLink *link) +{ + switch (link->type) { + case AVMEDIA_TYPE_VIDEO: return &negotiate_video; + case AVMEDIA_TYPE_AUDIO: return &negotiate_audio; + default: return NULL; + } +} + int ff_fmt_is_in(int fmt, const int *fmts) { const int *p; |