Fix race condition in concurrent subtitle conversion
SubtitleEncoder.ConvertSubtitles parsed subtitles with libse's static Subtitle.Parse, which iterates a statically cached list of shared SubtitleFormat instances. Format parsers keep mutable per-parse state on the instance, so concurrent subtitle requests corrupted each other's output (cues mixed across streams and languages, truncated files) or failed with NullReferenceException when format detection broke down and Subtitle.Parse returned null. Parse through the injected ISubtitleParser instead. SubtitleEditParser instantiates a fresh format parser per call, so requests no longer share state. Its Parse method now returns the libse Subtitle directly (the SubtitleTrackInfo flattening was unused since the SubtitleEdit writer rework) so the writers keep full fidelity such as ASS styling.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System.IO;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using Nikse.SubtitleEdit.Core.Common;
|
||||
|
||||
namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
{
|
||||
@@ -12,8 +12,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
/// </summary>
|
||||
/// <param name="stream">The stream.</param>
|
||||
/// <param name="fileExtension">The file extension.</param>
|
||||
/// <returns>SubtitleTrackInfo.</returns>
|
||||
SubtitleTrackInfo Parse(Stream stream, string fileExtension);
|
||||
/// <returns>The parsed subtitle.</returns>
|
||||
Subtitle Parse(Stream stream, string fileExtension);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the file extension is supported by the parser.
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Nikse.SubtitleEdit.Core.Common;
|
||||
using SubtitleFormat = Nikse.SubtitleEdit.Core.SubtitleFormats.SubtitleFormat;
|
||||
@@ -30,7 +28,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public SubtitleTrackInfo Parse(Stream stream, string fileExtension)
|
||||
public Subtitle Parse(Stream stream, string fileExtension)
|
||||
{
|
||||
var subtitle = new Subtitle();
|
||||
var lines = stream.ReadAllLines().ToList();
|
||||
@@ -76,21 +74,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
throw new ArgumentException("Unsupported format: " + fileExtension);
|
||||
}
|
||||
|
||||
var trackInfo = new SubtitleTrackInfo();
|
||||
int len = subtitle.Paragraphs.Count;
|
||||
var trackEvents = new SubtitleTrackEvent[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
var p = subtitle.Paragraphs[i];
|
||||
trackEvents[i] = new SubtitleTrackEvent(p.Number.ToString(CultureInfo.InvariantCulture), p.Text)
|
||||
{
|
||||
StartPositionTicks = p.StartTime.TimeSpan.Ticks,
|
||||
EndPositionTicks = p.EndTime.TimeSpan.Ticks
|
||||
};
|
||||
}
|
||||
|
||||
trackInfo.TrackEvents = trackEvents;
|
||||
return trackInfo;
|
||||
return subtitle;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
_serverConfigurationManager = serverConfigurationManager;
|
||||
}
|
||||
|
||||
private MemoryStream ConvertSubtitles(
|
||||
internal MemoryStream ConvertSubtitles(
|
||||
Stream stream,
|
||||
SubtitleInfo inputInfo,
|
||||
string outputFormat,
|
||||
@@ -81,7 +81,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||
long endTimeTicks,
|
||||
bool preserveOriginalTimestamps)
|
||||
{
|
||||
var subtitle = Subtitle.Parse(stream, Path.GetExtension(inputInfo.Path));
|
||||
var subtitle = _subtitleParser.Parse(stream, inputInfo.Format);
|
||||
|
||||
FilterEvents(subtitle, startTimeTicks, endTimeTicks, preserveOriginalTimestamps);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user