fix: accessing Standard* of a Process requires manually disposing them afterwards (#10125)

This commit is contained in:
Claus Vium 2023-08-20 20:06:57 +02:00 committed by GitHub
parent 260680d727
commit 956e3dab43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 56 additions and 48 deletions

View File

@ -620,7 +620,7 @@ public class TranscodingJobHelper : IDisposable
state.TranscodingJob = transcodingJob; state.TranscodingJob = transcodingJob;
// Important - don't await the log task or we won't be able to kill FFmpeg when the user stops playback // Important - don't await the log task or we won't be able to kill FFmpeg when the user stops playback
_ = new JobLogger(_logger).StartStreamingLog(state, process.StandardError.BaseStream, logStream); _ = new JobLogger(_logger).StartStreamingLog(state, process.StandardError, logStream);
// Wait for the file to exist before proceeding // Wait for the file to exist before proceeding
var ffmpegTargetFile = state.WaitForPath ?? outputPath; var ffmpegTargetFile = state.WaitForPath ?? outputPath;

View File

@ -20,12 +20,12 @@ namespace MediaBrowser.Controller.MediaEncoding
_logger = logger; _logger = logger;
} }
public async Task StartStreamingLog(EncodingJobInfo state, Stream source, Stream target) public async Task StartStreamingLog(EncodingJobInfo state, StreamReader reader, Stream target)
{ {
try try
{ {
using (target) using (target)
using (var reader = new StreamReader(source)) using (reader)
{ {
while (!reader.EndOfStream && reader.BaseStream.CanRead) while (!reader.EndOfStream && reader.BaseStream.CanRead)
{ {

View File

@ -553,7 +553,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
private string GetProcessOutput(string path, string arguments, bool readStdErr, string? testKey) private string GetProcessOutput(string path, string arguments, bool readStdErr, string? testKey)
{ {
using (var process = new Process() var redirectStandardIn = !string.IsNullOrEmpty(testKey);
using (var process = new Process
{ {
StartInfo = new ProcessStartInfo(path, arguments) StartInfo = new ProcessStartInfo(path, arguments)
{ {
@ -561,7 +562,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
UseShellExecute = false, UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden, WindowStyle = ProcessWindowStyle.Hidden,
ErrorDialog = false, ErrorDialog = false,
RedirectStandardInput = !string.IsNullOrEmpty(testKey), RedirectStandardInput = redirectStandardIn,
RedirectStandardOutput = true, RedirectStandardOutput = true,
RedirectStandardError = true RedirectStandardError = true
} }
@ -571,12 +572,14 @@ namespace MediaBrowser.MediaEncoding.Encoder
process.Start(); process.Start();
if (!string.IsNullOrEmpty(testKey)) if (redirectStandardIn)
{ {
process.StandardInput.Write(testKey); using var writer = process.StandardInput;
writer.Write(testKey);
} }
return readStdErr ? process.StandardError.ReadToEnd() : process.StandardOutput.ReadToEnd(); using var reader = readStdErr ? process.StandardError : process.StandardOutput;
return reader.ReadToEnd();
} }
} }
} }

View File

@ -511,7 +511,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
using (var processWrapper = new ProcessWrapper(process, this)) using (var processWrapper = new ProcessWrapper(process, this))
{ {
StartProcess(processWrapper); StartProcess(processWrapper);
await process.StandardOutput.BaseStream.CopyToAsync(memoryStream, cancellationToken).ConfigureAwait(false); using var reader = process.StandardOutput;
await reader.BaseStream.CopyToAsync(memoryStream, cancellationToken).ConfigureAwait(false);
memoryStream.Seek(0, SeekOrigin.Begin); memoryStream.Seek(0, SeekOrigin.Begin);
InternalMediaInfoResult result; InternalMediaInfoResult result;
try try

View File

@ -130,7 +130,8 @@ namespace MediaBrowser.Providers.MediaInfo
throw; throw;
} }
output = await process.StandardError.ReadToEndAsync(cancellationToken).ConfigureAwait(false); using var reader = process.StandardError;
output = await reader.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
MatchCollection split = LUFSRegex().Matches(output); MatchCollection split = LUFSRegex().Matches(output);

View File

@ -68,51 +68,54 @@ public static class FfProbeKeyframeExtractor
double streamDuration = 0; double streamDuration = 0;
double formatDuration = 0; double formatDuration = 0;
while (!reader.EndOfStream) using (reader)
{ {
var line = reader.ReadLine().AsSpan(); while (!reader.EndOfStream)
if (line.IsEmpty)
{ {
continue; var line = reader.ReadLine().AsSpan();
} if (line.IsEmpty)
var firstComma = line.IndexOf(',');
var lineType = line[..firstComma];
var rest = line[(firstComma + 1)..];
if (lineType.Equals("packet", StringComparison.OrdinalIgnoreCase))
{
// Split time and flags from the packet line. Example line: packet,7169.079000,K_
var secondComma = rest.IndexOf(',');
var ptsTime = rest[..secondComma];
var flags = rest[(secondComma + 1)..];
if (flags.StartsWith("K_"))
{ {
if (double.TryParse(ptsTime, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var keyframe)) continue;
}
var firstComma = line.IndexOf(',');
var lineType = line[..firstComma];
var rest = line[(firstComma + 1)..];
if (lineType.Equals("packet", StringComparison.OrdinalIgnoreCase))
{
// Split time and flags from the packet line. Example line: packet,7169.079000,K_
var secondComma = rest.IndexOf(',');
var ptsTime = rest[..secondComma];
var flags = rest[(secondComma + 1)..];
if (flags.StartsWith("K_"))
{ {
// Have to manually convert to ticks to avoid rounding errors as TimeSpan is only precise down to 1 ms when converting double. if (double.TryParse(ptsTime, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var keyframe))
keyframes.Add(Convert.ToInt64(keyframe * TimeSpan.TicksPerSecond)); {
// Have to manually convert to ticks to avoid rounding errors as TimeSpan is only precise down to 1 ms when converting double.
keyframes.Add(Convert.ToInt64(keyframe * TimeSpan.TicksPerSecond));
}
}
}
else if (lineType.Equals("stream", StringComparison.OrdinalIgnoreCase))
{
if (double.TryParse(rest, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var streamDurationResult))
{
streamDuration = streamDurationResult;
}
}
else if (lineType.Equals("format", StringComparison.OrdinalIgnoreCase))
{
if (double.TryParse(rest, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var formatDurationResult))
{
formatDuration = formatDurationResult;
} }
} }
} }
else if (lineType.Equals("stream", StringComparison.OrdinalIgnoreCase))
{ // Prefer the stream duration as it should be more accurate
if (double.TryParse(rest, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var streamDurationResult)) var duration = streamDuration > 0 ? streamDuration : formatDuration;
{
streamDuration = streamDurationResult; return new KeyframeData(TimeSpan.FromSeconds(duration).Ticks, keyframes);
}
}
else if (lineType.Equals("format", StringComparison.OrdinalIgnoreCase))
{
if (double.TryParse(rest, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var formatDurationResult))
{
formatDuration = formatDurationResult;
}
}
} }
// Prefer the stream duration as it should be more accurate
var duration = streamDuration > 0 ? streamDuration : formatDuration;
return new KeyframeData(TimeSpan.FromSeconds(duration).Ticks, keyframes);
} }
} }