mirror of
https://github.com/rosenbjerg/FFMpegCore.git
synced 2024-11-10 08:34:12 +01:00
Merge pull request #226 from rosenbjerg/master
v.4.4.0
Former-commit-id: 7ebb47d757
This commit is contained in:
commit
12084323f5
8 changed files with 114 additions and 7 deletions
|
@ -12,6 +12,7 @@
|
||||||
using FFMpegCore.Arguments;
|
using FFMpegCore.Arguments;
|
||||||
using FFMpegCore.Exceptions;
|
using FFMpegCore.Exceptions;
|
||||||
using FFMpegCore.Pipes;
|
using FFMpegCore.Pipes;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace FFMpegCore.Test
|
namespace FFMpegCore.Test
|
||||||
{
|
{
|
||||||
|
@ -612,5 +613,64 @@ public async Task Video_Cancel_Async_With_Timeout()
|
||||||
Assert.AreEqual("h264", outputInfo.PrimaryVideoStream.CodecName);
|
Assert.AreEqual("h264", outputInfo.PrimaryVideoStream.CodecName);
|
||||||
Assert.AreEqual("aac", outputInfo.PrimaryAudioStream!.CodecName);
|
Assert.AreEqual("aac", outputInfo.PrimaryAudioStream!.CodecName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod, Timeout(10000)]
|
||||||
|
public async Task Video_Cancel_CancellationToken_Async()
|
||||||
|
{
|
||||||
|
var outputFile = new TemporaryFile("out.mp4");
|
||||||
|
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
var task = FFMpegArguments
|
||||||
|
.FromFileInput("testsrc2=size=320x240[out0]; sine[out1]", false, args => args
|
||||||
|
.WithCustomArgument("-re")
|
||||||
|
.ForceFormat("lavfi"))
|
||||||
|
.OutputToFile(outputFile, false, opt => opt
|
||||||
|
.WithAudioCodec(AudioCodec.Aac)
|
||||||
|
.WithVideoCodec(VideoCodec.LibX264)
|
||||||
|
.WithSpeedPreset(Speed.VeryFast))
|
||||||
|
.CancellableThrough(cts.Token)
|
||||||
|
.ProcessAsynchronously(false);
|
||||||
|
|
||||||
|
await Task.Delay(300);
|
||||||
|
cts.Cancel();
|
||||||
|
|
||||||
|
var result = await task;
|
||||||
|
|
||||||
|
Assert.IsFalse(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod, Timeout(10000)]
|
||||||
|
public async Task Video_Cancel_CancellationToken_Async_With_Timeout()
|
||||||
|
{
|
||||||
|
var outputFile = new TemporaryFile("out.mp4");
|
||||||
|
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
var task = FFMpegArguments
|
||||||
|
.FromFileInput("testsrc2=size=320x240[out0]; sine[out1]", false, args => args
|
||||||
|
.WithCustomArgument("-re")
|
||||||
|
.ForceFormat("lavfi"))
|
||||||
|
.OutputToFile(outputFile, false, opt => opt
|
||||||
|
.WithAudioCodec(AudioCodec.Aac)
|
||||||
|
.WithVideoCodec(VideoCodec.LibX264)
|
||||||
|
.WithSpeedPreset(Speed.VeryFast))
|
||||||
|
.CancellableThrough(cts.Token, 5000)
|
||||||
|
.ProcessAsynchronously(false);
|
||||||
|
|
||||||
|
await Task.Delay(300);
|
||||||
|
cts.Cancel();
|
||||||
|
|
||||||
|
var result = await task;
|
||||||
|
|
||||||
|
var outputInfo = await FFProbe.AnalyseAsync(outputFile);
|
||||||
|
|
||||||
|
Assert.IsTrue(result);
|
||||||
|
Assert.IsNotNull(outputInfo);
|
||||||
|
Assert.AreEqual(320, outputInfo.PrimaryVideoStream!.Width);
|
||||||
|
Assert.AreEqual(240, outputInfo.PrimaryVideoStream.Height);
|
||||||
|
Assert.AreEqual("h264", outputInfo.PrimaryVideoStream.CodecName);
|
||||||
|
Assert.AreEqual("aac", outputInfo.PrimaryAudioStream!.CodecName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,11 @@ public FFMpegArgumentProcessor CancellableThrough(out Action cancel, int timeout
|
||||||
cancel = () => CancelEvent?.Invoke(this, timeout);
|
cancel = () => CancelEvent?.Invoke(this, timeout);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
public FFMpegArgumentProcessor CancellableThrough(CancellationToken token, int timeout = 0)
|
||||||
|
{
|
||||||
|
token.Register(() => CancelEvent?.Invoke(this, timeout));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
public bool ProcessSynchronously(bool throwOnError = true, FFOptions? ffMpegOptions = null)
|
public bool ProcessSynchronously(bool throwOnError = true, FFOptions? ffMpegOptions = null)
|
||||||
{
|
{
|
||||||
using var instance = PrepareInstance(ffMpegOptions ?? GlobalFFOptions.Current, out var cancellationTokenSource);
|
using var instance = PrepareInstance(ffMpegOptions ?? GlobalFFOptions.Current, out var cancellationTokenSource);
|
||||||
|
|
|
@ -9,10 +9,11 @@
|
||||||
<Version>3.0.0.0</Version>
|
<Version>3.0.0.0</Version>
|
||||||
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
<AssemblyVersion>3.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>3.0.0.0</FileVersion>
|
<FileVersion>3.0.0.0</FileVersion>
|
||||||
<PackageReleaseNotes>- Added support for PCM audio through RawAudioPipeSource (thanks to Namaneo)
|
<PackageReleaseNotes>- Cancellation token support (thanks patagonaa)
|
||||||
- Removed -y in InputPipeArgument due to reported problems</PackageReleaseNotes>
|
- Support for setting stdout and stderr encoding for ffprobe (thanks CepheiSigma)
|
||||||
|
- Improved ffprobe exceptions</PackageReleaseNotes>
|
||||||
<LangVersion>8</LangVersion>
|
<LangVersion>8</LangVersion>
|
||||||
<PackageVersion>4.3.0</PackageVersion>
|
<PackageVersion>4.4.0</PackageVersion>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<Authors>Malte Rosenbjerg, Vlad Jerca, Max Bagryantsev</Authors>
|
<Authors>Malte Rosenbjerg, Vlad Jerca, Max Bagryantsev</Authors>
|
||||||
<PackageTags>ffmpeg ffprobe convert video audio mediafile resize analyze muxing</PackageTags>
|
<PackageTags>ffmpeg ffprobe convert video audio mediafile resize analyze muxing</PackageTags>
|
||||||
|
|
11
FFMpegCore/FFProbe/Exceptions/FFProbeException.cs
Normal file
11
FFMpegCore/FFProbe/Exceptions/FFProbeException.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace FFMpegCore.Exceptions
|
||||||
|
{
|
||||||
|
public class FFProbeException : Exception
|
||||||
|
{
|
||||||
|
public FFProbeException(string message, Exception? inner = null) : base(message, inner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
FFMpegCore/FFProbe/Exceptions/FFProbeProcessException.cs
Normal file
15
FFMpegCore/FFProbe/Exceptions/FFProbeProcessException.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace FFMpegCore.Exceptions
|
||||||
|
{
|
||||||
|
public class FFProbeProcessException : FFProbeException
|
||||||
|
{
|
||||||
|
public IReadOnlyCollection<string> ProcessErrors { get; }
|
||||||
|
|
||||||
|
public FFProbeProcessException(string message, IReadOnlyCollection<string> processErrors, Exception? inner = null) : base(message, inner)
|
||||||
|
{
|
||||||
|
ProcessErrors = processErrors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
FFMpegCore/FFProbe/Exceptions/FormatNullException.cs
Normal file
9
FFMpegCore/FFProbe/Exceptions/FormatNullException.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace FFMpegCore.Exceptions
|
||||||
|
{
|
||||||
|
public class FormatNullException : FFProbeException
|
||||||
|
{
|
||||||
|
public FormatNullException() : base("Format not specified")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -92,7 +93,7 @@ public static async Task<IMediaAnalysis> AnalyseAsync(Stream stream, int outputC
|
||||||
}
|
}
|
||||||
var exitCode = await task.ConfigureAwait(false);
|
var exitCode = await task.ConfigureAwait(false);
|
||||||
if (exitCode != 0)
|
if (exitCode != 0)
|
||||||
throw new FFMpegException(FFMpegExceptionType.Process, $"FFProbe process returned exit status {exitCode}", null, string.Join("\n", instance.ErrorData));
|
throw new FFProbeProcessException($"ffprobe exited with non-zero exit-code ({exitCode} - {string.Join("\n", instance.ErrorData)})", instance.ErrorData);
|
||||||
|
|
||||||
pipeArgument.Post();
|
pipeArgument.Post();
|
||||||
return ParseOutput(instance);
|
return ParseOutput(instance);
|
||||||
|
@ -107,7 +108,7 @@ private static IMediaAnalysis ParseOutput(Instance instance)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ffprobeAnalysis?.Format == null)
|
if (ffprobeAnalysis?.Format == null)
|
||||||
throw new Exception();
|
throw new FormatNullException();
|
||||||
|
|
||||||
return new MediaAnalysis(ffprobeAnalysis);
|
return new MediaAnalysis(ffprobeAnalysis);
|
||||||
}
|
}
|
||||||
|
@ -117,7 +118,12 @@ private static Instance PrepareInstance(string filePath, int outputCapacity, FFO
|
||||||
FFProbeHelper.RootExceptionCheck();
|
FFProbeHelper.RootExceptionCheck();
|
||||||
FFProbeHelper.VerifyFFProbeExists(ffOptions);
|
FFProbeHelper.VerifyFFProbeExists(ffOptions);
|
||||||
var arguments = $"-loglevel error -print_format json -show_format -sexagesimal -show_streams \"{filePath}\"";
|
var arguments = $"-loglevel error -print_format json -show_format -sexagesimal -show_streams \"{filePath}\"";
|
||||||
var instance = new Instance(GlobalFFOptions.GetFFProbeBinaryPath(), arguments) {DataBufferCapacity = outputCapacity};
|
var startInfo = new ProcessStartInfo(GlobalFFOptions.GetFFProbeBinaryPath(), arguments)
|
||||||
|
{
|
||||||
|
StandardOutputEncoding = ffOptions.Encoding,
|
||||||
|
StandardErrorEncoding = ffOptions.Encoding
|
||||||
|
};
|
||||||
|
var instance = new Instance(startInfo) { DataBufferCapacity = outputCapacity };
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ public static void VerifyFFProbeExists(FFOptions ffMpegOptions)
|
||||||
var (exitCode, _) = Instance.Finish(GlobalFFOptions.GetFFProbeBinaryPath(ffMpegOptions), "-version");
|
var (exitCode, _) = Instance.Finish(GlobalFFOptions.GetFFProbeBinaryPath(ffMpegOptions), "-version");
|
||||||
_ffprobeVerified = exitCode == 0;
|
_ffprobeVerified = exitCode == 0;
|
||||||
if (!_ffprobeVerified)
|
if (!_ffprobeVerified)
|
||||||
throw new FFMpegException(FFMpegExceptionType.Operation, "ffprobe was not found on your system");
|
throw new FFProbeException("ffprobe was not found on your system");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue