mirror of
https://github.com/rosenbjerg/FFMpegCore.git
synced 2026-01-15 01:15:45 +00:00
Merge 68d359b57e into cc75e03ec9
This commit is contained in:
commit
a0510b644a
2 changed files with 124 additions and 105 deletions
|
|
@ -30,6 +30,31 @@ public class FFProbeTests
|
||||||
Assert.IsTrue(frameAnalysis.Frames.All(f => f.MediaType == "video"));
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.MediaType == "video"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void FrameAnalysis_FromStream_Sync()
|
||||||
|
{
|
||||||
|
using var stream = File.OpenRead(TestResources.WebmVideo);
|
||||||
|
var frameAnalysis = FFProbe.GetFrames(stream);
|
||||||
|
|
||||||
|
Assert.HasCount(90, frameAnalysis.Frames);
|
||||||
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.PixelFormat == "yuv420p"));
|
||||||
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.Height == 360));
|
||||||
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.Width == 640));
|
||||||
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.MediaType == "video"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void FrameAnalysis_FromUri_Sync()
|
||||||
|
{
|
||||||
|
var frameAnalysis = FFProbe.GetFrames(new Uri(Path.GetFullPath(TestResources.WebmVideo)));
|
||||||
|
|
||||||
|
Assert.HasCount(90, frameAnalysis.Frames);
|
||||||
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.PixelFormat == "yuv420p"));
|
||||||
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.Height == 360));
|
||||||
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.Width == 640));
|
||||||
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.MediaType == "video"));
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task FrameAnalysis_Async()
|
public async Task FrameAnalysis_Async()
|
||||||
{
|
{
|
||||||
|
|
@ -42,6 +67,19 @@ public class FFProbeTests
|
||||||
Assert.IsTrue(frameAnalysis.Frames.All(f => f.MediaType == "video"));
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.MediaType == "video"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public async Task FrameAnalysis_FromStream_Async()
|
||||||
|
{
|
||||||
|
using var stream = File.OpenRead(TestResources.WebmVideo);
|
||||||
|
var frameAnalysis = await FFProbe.GetFramesAsync(stream, cancellationToken: TestContext.CancellationToken);
|
||||||
|
|
||||||
|
Assert.HasCount(90, frameAnalysis.Frames);
|
||||||
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.PixelFormat == "yuv420p"));
|
||||||
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.Height == 360));
|
||||||
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.Width == 640));
|
||||||
|
Assert.IsTrue(frameAnalysis.Frames.All(f => f.MediaType == "video"));
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public async Task PacketAnalysis_Async()
|
public async Task PacketAnalysis_Async()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,121 +13,30 @@ public static class FFProbe
|
||||||
{
|
{
|
||||||
public static IMediaAnalysis Analyse(string filePath, FFOptions? ffOptions = null, string? customArguments = null)
|
public static IMediaAnalysis Analyse(string filePath, FFOptions? ffOptions = null, string? customArguments = null)
|
||||||
{
|
{
|
||||||
ThrowIfInputFileDoesNotExist(filePath);
|
return AnalyseAsync(filePath, ffOptions, CancellationToken.None, customArguments).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
|
||||||
var processArguments = PrepareStreamAnalysisInstance(filePath, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
|
||||||
var result = processArguments.StartAndWaitForExit();
|
|
||||||
ThrowIfExitCodeNotZero(result);
|
|
||||||
|
|
||||||
return ParseOutput(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static FFProbeFrames GetFrames(string filePath, FFOptions? ffOptions = null, string? customArguments = null)
|
|
||||||
{
|
|
||||||
ThrowIfInputFileDoesNotExist(filePath);
|
|
||||||
|
|
||||||
var instance = PrepareFrameAnalysisInstance(filePath, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
|
||||||
var result = instance.StartAndWaitForExit();
|
|
||||||
ThrowIfExitCodeNotZero(result);
|
|
||||||
|
|
||||||
return ParseFramesOutput(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static FFProbePackets GetPackets(string filePath, FFOptions? ffOptions = null, string? customArguments = null)
|
|
||||||
{
|
|
||||||
ThrowIfInputFileDoesNotExist(filePath);
|
|
||||||
|
|
||||||
var instance = PreparePacketAnalysisInstance(filePath, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
|
||||||
var result = instance.StartAndWaitForExit();
|
|
||||||
ThrowIfExitCodeNotZero(result);
|
|
||||||
|
|
||||||
return ParsePacketsOutput(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IMediaAnalysis Analyse(Uri uri, FFOptions? ffOptions = null, string? customArguments = null)
|
public static IMediaAnalysis Analyse(Uri uri, FFOptions? ffOptions = null, string? customArguments = null)
|
||||||
{
|
{
|
||||||
var instance = PrepareStreamAnalysisInstance(uri.AbsoluteUri, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
return AnalyseAsync(uri, ffOptions, CancellationToken.None, customArguments).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
var result = instance.StartAndWaitForExit();
|
|
||||||
ThrowIfExitCodeNotZero(result);
|
|
||||||
|
|
||||||
return ParseOutput(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IMediaAnalysis Analyse(Stream stream, FFOptions? ffOptions = null, string? customArguments = null)
|
public static IMediaAnalysis Analyse(Stream stream, FFOptions? ffOptions = null, string? customArguments = null)
|
||||||
{
|
{
|
||||||
var streamPipeSource = new StreamPipeSource(stream);
|
return AnalyseAsync(stream, ffOptions, CancellationToken.None, customArguments).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
var pipeArgument = new InputPipeArgument(streamPipeSource);
|
|
||||||
var instance = PrepareStreamAnalysisInstance(pipeArgument.PipePath, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
|
||||||
pipeArgument.Pre();
|
|
||||||
|
|
||||||
var task = instance.StartAndWaitForExitAsync();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
pipeArgument.During().ConfigureAwait(false).GetAwaiter().GetResult();
|
|
||||||
}
|
|
||||||
catch (IOException) { }
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
pipeArgument.Post();
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = task.ConfigureAwait(false).GetAwaiter().GetResult();
|
|
||||||
ThrowIfExitCodeNotZero(result);
|
|
||||||
|
|
||||||
return ParseOutput(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<IMediaAnalysis> AnalyseAsync(string filePath, FFOptions? ffOptions = null, CancellationToken cancellationToken = default,
|
public static async Task<IMediaAnalysis> AnalyseAsync(string filePath, FFOptions? ffOptions = null, CancellationToken cancellationToken = default,
|
||||||
string? customArguments = null)
|
string? customArguments = null)
|
||||||
{
|
{
|
||||||
ThrowIfInputFileDoesNotExist(filePath);
|
ThrowIfInputFileDoesNotExist(filePath);
|
||||||
|
return await AnalyseCoreAsync(filePath, ffOptions, cancellationToken, customArguments).ConfigureAwait(false);
|
||||||
var instance = PrepareStreamAnalysisInstance(filePath, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
|
||||||
var result = await instance.StartAndWaitForExitAsync(cancellationToken).ConfigureAwait(false);
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
|
||||||
ThrowIfExitCodeNotZero(result);
|
|
||||||
|
|
||||||
return ParseOutput(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static FFProbeFrames GetFrames(Uri uri, FFOptions? ffOptions = null, string? customArguments = null)
|
|
||||||
{
|
|
||||||
var instance = PrepareFrameAnalysisInstance(uri.AbsoluteUri, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
|
||||||
var result = instance.StartAndWaitForExit();
|
|
||||||
ThrowIfExitCodeNotZero(result);
|
|
||||||
|
|
||||||
return ParseFramesOutput(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<FFProbeFrames> GetFramesAsync(string filePath, FFOptions? ffOptions = null, CancellationToken cancellationToken = default,
|
|
||||||
string? customArguments = null)
|
|
||||||
{
|
|
||||||
ThrowIfInputFileDoesNotExist(filePath);
|
|
||||||
|
|
||||||
var instance = PrepareFrameAnalysisInstance(filePath, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
|
||||||
var result = await instance.StartAndWaitForExitAsync(cancellationToken).ConfigureAwait(false);
|
|
||||||
return ParseFramesOutput(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<FFProbePackets> GetPacketsAsync(string filePath, FFOptions? ffOptions = null, CancellationToken cancellationToken = default,
|
|
||||||
string? customArguments = null)
|
|
||||||
{
|
|
||||||
ThrowIfInputFileDoesNotExist(filePath);
|
|
||||||
|
|
||||||
var instance = PreparePacketAnalysisInstance(filePath, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
|
||||||
var result = await instance.StartAndWaitForExitAsync(cancellationToken).ConfigureAwait(false);
|
|
||||||
return ParsePacketsOutput(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<IMediaAnalysis> AnalyseAsync(Uri uri, FFOptions? ffOptions = null, CancellationToken cancellationToken = default,
|
public static async Task<IMediaAnalysis> AnalyseAsync(Uri uri, FFOptions? ffOptions = null, CancellationToken cancellationToken = default,
|
||||||
string? customArguments = null)
|
string? customArguments = null)
|
||||||
{
|
{
|
||||||
var instance = PrepareStreamAnalysisInstance(uri.AbsoluteUri, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
return await AnalyseCoreAsync(uri.IsFile ? uri.LocalPath : uri.AbsoluteUri, ffOptions, cancellationToken, customArguments).ConfigureAwait(false);
|
||||||
var result = await instance.StartAndWaitForExitAsync(cancellationToken).ConfigureAwait(false);
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
|
||||||
ThrowIfExitCodeNotZero(result);
|
|
||||||
|
|
||||||
return ParseOutput(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<IMediaAnalysis> AnalyseAsync(Stream stream, FFOptions? ffOptions = null, CancellationToken cancellationToken = default,
|
public static async Task<IMediaAnalysis> AnalyseAsync(Stream stream, FFOptions? ffOptions = null, CancellationToken cancellationToken = default,
|
||||||
|
|
@ -135,10 +44,10 @@ public static class FFProbe
|
||||||
{
|
{
|
||||||
var streamPipeSource = new StreamPipeSource(stream);
|
var streamPipeSource = new StreamPipeSource(stream);
|
||||||
var pipeArgument = new InputPipeArgument(streamPipeSource);
|
var pipeArgument = new InputPipeArgument(streamPipeSource);
|
||||||
var instance = PrepareStreamAnalysisInstance(pipeArgument.PipePath, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
|
||||||
pipeArgument.Pre();
|
|
||||||
|
|
||||||
var task = instance.StartAndWaitForExitAsync(cancellationToken);
|
var task = AnalyseCoreAsync(pipeArgument.PipePath, ffOptions ?? GlobalFFOptions.Current, cancellationToken, customArguments);
|
||||||
|
|
||||||
|
pipeArgument.Pre();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await pipeArgument.During(cancellationToken).ConfigureAwait(false);
|
await pipeArgument.During(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
@ -151,22 +60,94 @@ public static class FFProbe
|
||||||
pipeArgument.Post();
|
pipeArgument.Post();
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await task.ConfigureAwait(false);
|
return await task.ConfigureAwait(false);
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
}
|
||||||
ThrowIfExitCodeNotZero(result);
|
|
||||||
|
|
||||||
pipeArgument.Post();
|
public static FFProbeFrames GetFrames(string filePath, FFOptions? ffOptions = null, string? customArguments = null)
|
||||||
return ParseOutput(result);
|
{
|
||||||
|
return GetFramesAsync(filePath, ffOptions, CancellationToken.None, customArguments).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FFProbeFrames GetFrames(Uri uri, FFOptions? ffOptions = null, string? customArguments = null)
|
||||||
|
{
|
||||||
|
return GetFramesAsync(uri, ffOptions, CancellationToken.None, customArguments).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FFProbeFrames GetFrames(Stream stream, FFOptions? ffOptions = null, string? customArguments = null)
|
||||||
|
{
|
||||||
|
return GetFramesAsync(stream, ffOptions, CancellationToken.None, customArguments).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<FFProbeFrames> GetFramesAsync(string filePath, FFOptions? ffOptions = null, CancellationToken cancellationToken = default,
|
||||||
|
string? customArguments = null)
|
||||||
|
{
|
||||||
|
ThrowIfInputFileDoesNotExist(filePath);
|
||||||
|
return await GetFramesCoreAsync(filePath, ffOptions, cancellationToken, customArguments).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<FFProbeFrames> GetFramesAsync(Uri uri, FFOptions? ffOptions = null, CancellationToken cancellationToken = default,
|
public static async Task<FFProbeFrames> GetFramesAsync(Uri uri, FFOptions? ffOptions = null, CancellationToken cancellationToken = default,
|
||||||
string? customArguments = null)
|
string? customArguments = null)
|
||||||
{
|
{
|
||||||
var instance = PrepareFrameAnalysisInstance(uri.AbsoluteUri, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
return await GetFramesCoreAsync(uri.IsFile ? uri.LocalPath : uri.AbsoluteUri, ffOptions, cancellationToken, customArguments).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<FFProbeFrames> GetFramesAsync(Stream stream, FFOptions? ffOptions = null, CancellationToken cancellationToken = default,
|
||||||
|
string? customArguments = null)
|
||||||
|
{
|
||||||
|
var streamPipeSource = new StreamPipeSource(stream);
|
||||||
|
var pipeArgument = new InputPipeArgument(streamPipeSource);
|
||||||
|
|
||||||
|
var task = GetFramesCoreAsync(pipeArgument.PipePath, ffOptions ?? GlobalFFOptions.Current, cancellationToken, customArguments);
|
||||||
|
|
||||||
|
pipeArgument.Pre();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await pipeArgument.During(cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (IOException) { }
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
pipeArgument.Post();
|
||||||
|
}
|
||||||
|
|
||||||
|
return await task.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<IMediaAnalysis> AnalyseCoreAsync(string inputPath, FFOptions? ffOptions, CancellationToken cancellationToken, string? customArguments)
|
||||||
|
{
|
||||||
|
var instance = PrepareStreamAnalysisInstance(inputPath, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
||||||
var result = await instance.StartAndWaitForExitAsync(cancellationToken).ConfigureAwait(false);
|
var result = await instance.StartAndWaitForExitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
ThrowIfExitCodeNotZero(result);
|
||||||
|
|
||||||
|
return ParseOutput(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<FFProbeFrames> GetFramesCoreAsync(string inputPath, FFOptions? ffOptions, CancellationToken cancellationToken, string? customArguments)
|
||||||
|
{
|
||||||
|
var instance = PrepareFrameAnalysisInstance(inputPath, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
||||||
|
var result = await instance.StartAndWaitForExitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
ThrowIfExitCodeNotZero(result);
|
||||||
|
|
||||||
return ParseFramesOutput(result);
|
return ParseFramesOutput(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static FFProbePackets GetPackets(string filePath, FFOptions? ffOptions = null, string? customArguments = null)
|
||||||
|
{
|
||||||
|
return GetPacketsAsync(filePath, ffOptions, CancellationToken.None, customArguments).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<FFProbePackets> GetPacketsAsync(string filePath, FFOptions? ffOptions = null, CancellationToken cancellationToken = default,
|
||||||
|
string? customArguments = null)
|
||||||
|
{
|
||||||
|
ThrowIfInputFileDoesNotExist(filePath);
|
||||||
|
|
||||||
|
var instance = PreparePacketAnalysisInstance(filePath, ffOptions ?? GlobalFFOptions.Current, customArguments);
|
||||||
|
var result = await instance.StartAndWaitForExitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
return ParsePacketsOutput(result);
|
||||||
|
}
|
||||||
|
|
||||||
private static IMediaAnalysis ParseOutput(IProcessResult instance)
|
private static IMediaAnalysis ParseOutput(IProcessResult instance)
|
||||||
{
|
{
|
||||||
var json = string.Join(string.Empty, instance.OutputData);
|
var json = string.Join(string.Empty, instance.OutputData);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue