1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-18 03:19:31 +02:00
Commit Graph

61 Commits

Author SHA1 Message Date
James Almer
1f96db959c avfilter: convert to new channel layout API
Signed-off-by: James Almer <jamrial@gmail.com>
2022-03-15 09:42:46 -03:00
Paul B Mahol
c439c6b191 avfilter/af_headphone: improve stereo hrir support
Until now, in some cases produced output would be wrong.
2022-02-19 13:45:47 +01:00
Andreas Rheinhardt
b4f5201967 avfilter: Replace query_formats callback with union of list and callback
If one looks at the many query_formats callbacks in existence,
one will immediately recognize that there is one type of default
callback for video and a slightly different default callback for
audio: It is "return ff_set_common_formats_from_list(ctx, pix_fmts);"
for video with a filter-specific pix_fmts list. For audio, it is
the same with a filter-specific sample_fmts list together with
ff_set_common_all_samplerates() and ff_set_common_all_channel_counts().

This commit allows to remove the boilerplate query_formats callbacks
by replacing said callback with a union consisting the old callback
and pointers for pixel and sample format arrays. For the not uncommon
case in which these lists only contain a single entry (besides the
sentinel) enum AVPixelFormat and enum AVSampleFormat fields are also
added to the union to store them directly in the AVFilter,
thereby avoiding a relocation.

The state of said union will be contained in a new, dedicated AVFilter
field (the nb_inputs and nb_outputs fields have been shrunk to uint8_t
in order to create a hole for this new field; this is no problem, as
the maximum of all the nb_inputs is four; for nb_outputs it is only
two).

The state's default value coincides with the earlier default of
query_formats being unset, namely that the filter accepts all formats
(and also sample rates and channel counts/layouts for audio)
provided that these properties agree coincide for all inputs and
outputs.

By using different union members for audio and video filters
the type-unsafety of using the same functions for audio and video
lists will furthermore be more confined to formats.c than before.

When the new fields are used, they will also avoid allocations:
Currently something nearly equivalent to ff_default_query_formats()
is called after every successful call to a query_formats callback;
yet in the common case that the newly allocated AVFilterFormats
are not used at all (namely if there are no free links) these newly
allocated AVFilterFormats are freed again without ever being used.
Filters no longer using the callback will not exhibit this any more.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Reviewed-by: Nicolas George <george@nsup.org>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-10-05 17:48:25 +02:00
Andreas Rheinhardt
ad5d056dc3 avfilter/af_headphone: Free inpads' names generically
Reviewed-by: Nicolas George <george@nsup.org>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-08-22 16:13:44 +02:00
Andreas Rheinhardt
8be701d9f7 avfilter/avfilter: Add numbers of (in|out)pads directly to AVFilter
Up until now, an AVFilter's lists of input and output AVFilterPads
were terminated by a sentinel and the only way to get the length
of these lists was by using avfilter_pad_count(). This has two
drawbacks: first, sizeof(AVFilterPad) is not negligible
(i.e. 64B on 64bit systems); second, getting the size involves
a function call instead of just reading the data.

This commit therefore changes this. The sentinels are removed and new
private fields nb_inputs and nb_outputs are added to AVFilter that
contain the number of elements of the respective AVFilterPad array.

Given that AVFilter.(in|out)puts are the only arrays of zero-terminated
AVFilterPads an API user has access to (AVFilterContext.(in|out)put_pads
are not zero-terminated and they already have a size field) the argument
to avfilter_pad_count() is always one of these lists, so it just has to
find the filter the list belongs to and read said number. This is slower
than before, but a replacement function that just reads the internal numbers
that users are expected to switch to will be added soon; and furthermore,
avfilter_pad_count() is probably never called in hot loops anyway.

This saves about 49KiB from the binary; notice that these sentinels are
not in .bss despite being zeroed: they are in .data.rel.ro due to the
non-sentinels.

Reviewed-by: Nicolas George <george@nsup.org>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-08-20 12:53:58 +02:00
Andreas Rheinhardt
515e7fbce1 avfilter/avfilter: Remove unused feature to add pads in the middle
Reviewed-by: Nicolas George <george@nsup.org>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-08-17 21:20:59 +02:00
Andreas Rheinhardt
1b20853fb3 avfilter/internal: Factor out executing a filter's execute_func
The current way of doing it involves writing the ctx parameter twice.

Reviewed-by: Nicolas George <george@nsup.org>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-08-15 21:33:25 +02:00
Andreas Rheinhardt
18ec426a86 avfilter/formats: Factor common function combinations out
Several combinations of functions happen quite often in query_format
functions; e.g. ff_set_common_formats(ctx, ff_make_format_list(sample_fmts))
is very common. This commit therefore adds functions that are equivalent
to commonly used function combinations in order to reduce code
duplication.

Reviewed-by: Nicolas George <george@nsup.org>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-08-13 17:36:22 +02:00
Paul B Mahol
88b6342c2b avfilter/af_headphone: switch to TX FFT from avutil 2021-07-24 12:24:40 +02:00
Andreas Rheinhardt
a04ad248a0 avfilter: Constify all AVFilters
This is possible now that the next-API is gone.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Signed-off-by: James Almer <jamrial@gmail.com>
2021-04-27 11:48:05 -03:00
Andreas Rheinhardt
3e950f5349 avfilter/af_headphone: Don't check for clipping in separate loop
Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:48:24 +02:00
Andreas Rheinhardt
7b841cf6b7 avfilter/af_headphone: Remove pointless additions
buffer_length is a power-of-two and modulo is buffer_length - 1, so that
buffer_length & modulo is zero.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:48:18 +02:00
Andreas Rheinhardt
8dda0d601b avfilter/af_headphone: Use more appropriate variable name
Also unify incrementing the variable containing the pointer
to the currently used HRIR data.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:48:06 +02:00
Andreas Rheinhardt
bb8ab733c2 avfilter/af_headphone: Avoid indirection for function pointer
Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:48:01 +02:00
Andreas Rheinhardt
6ada3c8368 avfilter/af_headphone: Avoid allocating array
Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:47:51 +02:00
Andreas Rheinhardt
6d0d25eca3 avfilter/af_headphone: Don't allocate unused element in array
The headphone filter uses an array with as many elements as the
filter has inputs to store some per-input information; yet actually it
only stores information for all inputs except the very first one (which
is special for this filter). Therefore this commit modifies the code to
remove this unused element.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:47:46 +02:00
Andreas Rheinhardt
990d9dd800 avfilter/af_headphone: Only keep one AVFrame at a time
Despite the headphone filter only using one AVFrame at a time, it kept
an array each of whose entries contained a pointer to an AVFrame at all
times; the pointers were mostly NULL. This commit instead replaces them
by using a single pointer to an AVFrame on the stack of the only
function that actually uses them.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:47:40 +02:00
Andreas Rheinhardt
abe0a5dd0a avfilter/af_headphone: Avoid intermediate buffer III
The headphone filter allocates a pair of buffers to be used as
intermediate buffers lateron: Before every use they are zeroed, then
some elements of the buffer are set and lateron the complete buffers are
copied into another, bigger buffer. These intermediate buffers are
unnecessary as the data can be directly written into the bigger buffer.
Furthermore, the whole buffer has been zeroed initially and because no
piece of this buffer is set twice (due to the fact that duplicate
channel map entries are skipped), it is unnecessary to rezero the part
of the big buffer that is about to be written to.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:47:35 +02:00
Andreas Rheinhardt
9d1f58424a avfilter/af_headphone: Simplify finding channel index
Before this commit, the headphone filter called
av_channel_layout_extract_channel() in a loop in order to find out
the index of a channel (given via its AV_CH_* value) in a channel layout.
This commit changes this to av_get_channel_layout_channel_index()
instead.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:47:30 +02:00
Andreas Rheinhardt
0952f8f909 avfilter/af_headphone: Fix channel assignment
The documentation of the map argument of the headphone filter states:

"Set mapping of input streams for convolution. The argument is a
’|’-separated list of channel names in order as they are given as
additional stream inputs for filter."

Yet this has not been honoured at all. Instead for the kth given HRIR
channel pair it was checked whether there was a kth mapping and if the
channel position so given was present in the channel layout of the main
input; if so, then the given HRIR channel pair was matched to the kth
channel of the main input. It should actually have been matched to the
channel given by the kth mapping. A consequence of the current algorithm
is that if N additional HRIR channel pairs are given, a permutation of
the first N entries of the mapping does not affect the output at all.

The old code might even set arrays belonging to streams that don't exist
(i.e. whose index is >= the number of channels of the main input
stream); these parts were not read lateron at all. The new code doesn't
do this any longer and therefore the number of elements of some of the
allocated arrays has been reduced (in case the number of mappings was
bigger than the number of channels of the first input stream).

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:47:24 +02:00
Andreas Rheinhardt
d883bca0f0 avfilter/af_headphone: Avoid intermediate buffers II
When the headphone filter is configured to perform its processing in the
frequency domain, it allocates (among other things) two pairs of
buffers, all of the same size. One pair is used to store data in it
during the initialization of the filter; the other pair is only
allocated lateron. It is zero-initialized and yet its data is
immediately overwritten by the content of the other pair of buffers
mentioned above; the latter pair is then freed.

This commit eliminates the pair of intermediate buffers.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:47:19 +02:00
Andreas Rheinhardt
f5e1d38b87 avfilter/af_headphone: Avoid intermediate buffers I
The headphone filter has two modes; in one of them (say A), it needs
certain buffers to store data. But it allocated them in both modes.
Furthermore when in mode A it also allocated intermediate buffers of the
same size, initialized them, copied their contents into the permanent
buffers and freed them.

This commit changes this: The permanent buffer is only allocated when
needed; the temporary buffer has been completely avoided.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:47:14 +02:00
Andreas Rheinhardt
a513b306b3 avfilter/af_headphone: Remove delay fields
They seem to exist for an option that was never implemented.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:47:09 +02:00
Andreas Rheinhardt
b2feca4616 avfilter/af_headphone: Remove unused arrays
The delay arrays were never properly initialized, only zero-initialized;
furthermore these arrays duplicate fields in the headphone_inputs
struct. So remove them.
(Btw: The allocations for them have not been checked.)

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:47:03 +02:00
Andreas Rheinhardt
bff1d0c658 avfilter/af_headphone: Avoid duplicating string needlessly
The string given by an AVOption that contains the channel assignment
is used only once; ergo it doesn't matter that parsing the string via
av_strtok() is destructive. There is no need to make a copy.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:46:58 +02:00
Andreas Rheinhardt
71daaafa3a avfilter/af_headphone: Simplify parsing channel mapping string
When parsing the channel mapping string (a string containing '|'
delimited tokens each of which is supposed to contain a channel name
like "FR"), the old code would at each step read up to seven uppercase
characters from the input string and give this to
av_get_channel_layout() to parse. The returned layout is then checked
for being a layout with a single channel set by computing its logarithm.

Besides being overtly complicated this also has the drawback of relying
on the assumption that every channel name consists of at most seven
uppercase letters only; but said assumption is wrong: The abbreviation
of the second low frequency channel is LFE2. Furthermore it treats
garbage like "FRfoo" as valid channel.

This commit changes this by using av_get_channel_layout() directly;
furthermore, av_get_channel_layout_nb_channels() (which uses popcount)
is used to find out the number of channels instead of the custom code
to calculate the logarithm.

(As a consequence, certain other formats to specify the channel layouts
are now accepted (like the hex versions of av_get_channel_layout()); but
this is actually not bad at all.)

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:46:51 +02:00
Andreas Rheinhardt
bc533ba2ae avfilter/af_headphone: Use uint64_t for channel mapping
The headphone filter has an option for the user to specify an assignment
of inputs to channels (or from pairs of channels of the second input to
channels). Up until now, these channels were stored in an int containing
the logarithm of the channel layout. Yet it is not the logarithm that is
used lateron and so a retransformation was necessary. Therefore this
commit simply stores the uint64_t as is, avoiding the retransformation.

This also has the advantage that unset channels (whose corresponding
entry is zero) can't be mistaken for valid channels any more; the old
code had to initialize the channels to -1 to solve this problem and had
to check for whether a channel is set before the retransformation
(because 1 << -1 is UB).

The only downside of this approach is that the size of the context
increases (by 256 bytes); but this is not exceedingly much.

Finally, the array has been moved to the end of the context; it is only
used a few times during the initialization process and moving it
decreased the offsets of lots of other entries, reducing codesize.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:46:30 +02:00
Andreas Rheinhardt
5e68727fa7 avfilter/af_headphone: Only attempt once to init coeffs
The headphone filter does most of its initialization after its init
function, because it can perform certain tasks only after all but its
first input streams have reached eof. When this happens, it allocates
certain buffers and errors out if an allocation fails.

Yet the filter didn't check whether some of these buffers already exist
(which may happen if an earlier attempt has been interrupted in the
middle (due to an allocation error)) in which case the old buffers leak.

This commit makes sure that initializing the buffers is only attempted
once; if not successfull at the first attempt, future calls to the
filter will error out. Trying to support resuming initialization doesn't
seem worthwhile.

Notice that some allocations were freed before a new allocation was
performed; yet this effort was incomplete. Said code has been removed.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:46:24 +02:00
Andreas Rheinhardt
a84c77396b avfilter/af_headphone: Combine several loops when checking for EOF
Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:46:18 +02:00
Andreas Rheinhardt
58b6594b01 avfilter/af_headphone: Fix stack buffer overflow
The number of channels can be up to 64, not only 16.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:46:13 +02:00
Andreas Rheinhardt
14226be499 avfilter/af_headphone: Don't overrun array
The headphone filter stores the channel position of the ith HRIR stream
in the ith element of an array of 64 elements; but because there is no
check for duplicate channels, it is easy to write beyond the end of the
array by simply repeating channels.

This commit adds a check for duplicate channels to rule this out.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:46:07 +02:00
Andreas Rheinhardt
7b74e02ef2 avfilter/af_headphone: Fix segfault when using very short streams
When the headphone filter does its processing in the time domain,
the lengths of the buffers involved are determined by three parameters,
only two of which are relevant here: ir_len and air_len. The former is
the length (in samples) of the longest HRIR input stream and the latter
is the smallest power-of-two bigger than ir_len.

Using optimized functions to calculate the convolution places
restrictions on the alignment of the length of the vectors whose scalar
product is calculated. Therefore said length, namely ir_len, is aligned
on 32; but the number of elements of the buffers used is given by air_len
and for ir_len < 16 a buffer overflow happens.

This commit fixes this by ensuring that air_len is always >= 32 if
processing happens in the time domain.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:45:59 +02:00
Andreas Rheinhardt
dfd46e2d16 avfilter/af_headphone: Check for the existence of samples
Not providing any samples makes no sense at all. And if no samples
were provided for one of the HRIR streams, one would either run into
an av_assert1 in ff_inlink_consume_samples() or into a segfault in
take_samples() in avfilter.c.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:45:39 +02:00
Andreas Rheinhardt
709fca0a94 avfilter/af_headphone: Remove always true check
Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:45:20 +02:00
Andreas Rheinhardt
e2d4a5807f avfilter/af_headphone: Don't use uninitialized buffer in log message
This buffer was supposed to be initialized by sscanf(input, "%7[A-Z]%n",
buf, &len), yet if the first input character is not in the A-Z range,
buf is not touched (in particular it needn't be zero-terminated if the
failure happened when parsing the first channel and it still contains
the last channel name if the failure happened when one channel name
could be successfully parsed). This is treated as error in which case
buf is used directly in the log message. This commit fixes this by
actually using the string that could not be matched in the log message
instead.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-09-09 13:36:54 +02:00
Nicolas George
2f76476549 lavfi: regroup formats lists in a single structure.
It will allow to refernce it as a whole without clunky macros.

Most of the changes have been automatically made with sed:

sed -i '
  s/-> *in_formats/->incfg.formats/g;
  s/-> *out_formats/->outcfg.formats/g;
  s/-> *in_channel_layouts/->incfg.channel_layouts/g;
  s/-> *out_channel_layouts/->outcfg.channel_layouts/g;
  s/-> *in_samplerates/->incfg.samplerates/g;
  s/-> *out_samplerates/->outcfg.samplerates/g;
  ' src/libavfilter/*(.)
2020-09-08 14:02:40 +02:00
Andreas Rheinhardt
ca8e5dedc7 avfilter/af_headphone: Fix leak of channel layouts list on error
In case the multichannel HRIR mode was enabled, an error could happen
between allocating a channel layouts list and attaching it to its target
destination. If an error happened, the list would leak. This is fixed by
attaching the list to its target directly after its allocation.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-08-26 23:52:57 +02:00
Andreas Rheinhardt
0960da42f5 avfilter/af_headphone: Fix segfault upon allocation failure
The headphone filter uses a variable number of inpads and allocates them
in its init function; if all goes well, the number of inpads coincides
with a number stored in the filter's private context. Yet if allocating a
subsequent inpad fails, the uninit function nevertheless uses the number
stored in the private context to determine the number of inpads to free
and not the AVFilterContext's nb_inputs. This will lead to an access
beyond the end of the allocated AVFilterContext.input_pads array and
an invalid free.

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
2020-08-26 23:52:56 +02:00
Paul B Mahol
dc33250765 avfilter/af_headphone: return on error immediately 2019-09-16 10:27:42 +02:00
Paul B Mahol
aece1eb1e9 avfilter/af_headphone: use av_log2() 2018-12-27 12:30:04 +01:00
Paul B Mahol
9ce96a744d avfilter/af_headphone: fix regression after 7c201e420 2018-12-26 10:41:41 +01:00
Paul B Mahol
6c7eb0708e avfilter/af_headphone: speed up fast convolution
Do IFFT only once per output channel.
2018-12-25 19:17:25 +01:00
Paul B Mahol
3bc711a267 avfilter/af_headphone: do not reduce LFE gain too much 2018-12-24 15:24:20 +01:00
Paul B Mahol
7c201e420a avfilter/af_headphone: fix filtering of non-power of 2 length IRs in time domain 2018-12-22 20:47:02 +01:00
Paul B Mahol
47ba085472 avfilter/af_headphone: use fabsf() instead of fabs() 2018-12-21 12:06:03 +01:00
Paul B Mahol
0f2cfa3d80 avfilter/af_headphone: do not leak input frames on error 2018-11-12 09:38:30 +01:00
Martin Vignali
75625c555c avfilter/af_headphone : fix mem leak
report by coverity
CID 1439934
CID 1439935
2018-11-09 21:55:32 +01:00
Paul B Mahol
6725fd8b0f avfilter/af_headphone: use lavfi internal queue instead
Signed-off-by: Paul B Mahol <onemda@gmail.com>
2018-10-04 12:10:20 +02:00
Paul B Mahol
9cf0079638 avfilter/af_headphone: switch to activate
Signed-off-by: Paul B Mahol <onemda@gmail.com>
2018-04-16 18:29:34 +02:00
Paul B Mahol
e1c8bd2389 avfilter/af_headphone: fix type=time with hrir=multich
Signed-off-by: Paul B Mahol <onemda@gmail.com>
2018-04-16 09:31:11 +02:00