fix: accessing Standard* of a Process requires manually disposing them afterwards (#10125)
This commit is contained in:
parent
260680d727
commit
956e3dab43
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user