`SubtitleFormat`'s `LoadSubtitle()` function is
not thread-safe.
A `SubtitleEditParser` instance's `Parse()`
function can be called from multiple threads at
the same time.
`SubtitleFormat`s are cached in the constructor
of each `SubtitleEditParser`, and the same
instances are used for each possibly parallel
`Parse()` function call, which causes subtitle
parse problems.
This patch modifies the code, so we only cache
the extension -> `SubtitleFormat` type/class
mapping and create a new `SubtitleFormat`
instance in each `Parse()` call, so no
`SubtitleFormat` instance is accessed from
multiple threads.
Fixes#12113
Kudos for everyone investigating the issue there,
most notably @RenV123 for PoC-ing the solution.
Signed-off-by: Attila Szakacs <szakacs.attila96@gmail.com>
Extracting a subtitle stream is a disk I/O bottlenecked operation as
ffmpeg has to read through the whole file, but usually there is nothing
CPU intensive to do.
If a file has multiple subtitle streams, and we want to extract more
of them, extracting them one-by-one results in reading the whole file
again and again.
However ffmpeg can extract multiple streams at once.
We can optimize this by extracting the subtitle streams all at once
when only one of them gets queried, then we will have all of them
cached for later use.
It is useful for people switching subtitles during playback.
It is even more useful for people who extract all the subtitle streams
in advance, for example with the "Subtitle Extract" plugin.
In this case we reduce the extraction time significantly based on the
number of subtitle streams in the files, which can be 5-10 in many
cases.
Signed-off-by: Attila Szakacs <szakacs.attila96@gmail.com>
Did a simple search/replace on the whole repo (except the RSSDP project)
This reduces LOC and should improve performance (methods containing a throw statement don't get inlined)
```
if \((\w+) == null\)
\s+\{
\s+throw new ArgumentNullException\((.*)\);
\s+\}
```
```
ArgumentNullException.ThrowIfNull($1);
```