diff --git a/MediaToolkit src/MediaToolkit.Test/Features/ArgumentsFeature.cs b/MediaToolkit src/MediaToolkit.Test/Features/ArgumentsFeature.cs new file mode 100644 index 0000000..253f98f --- /dev/null +++ b/MediaToolkit src/MediaToolkit.Test/Features/ArgumentsFeature.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using MediaToolkit.Util; +using NUnit.Framework; + +namespace MediaToolkit.Test.Features +{ + /* + * The FFmpeg library supports a huge range of arguments and the current implementation + * of CommandBuilder isn't really designed to allow clients to take full advantage of + * FFmpegs capabilities. So... about time we changed things up a little. + * + * + * + * ******/ + + + [TestFixture] + public class ArgumentsFeature + { + [Test] + public void BuildArgument() + { + string expectedOutput = @"-ss 20 -i ""test.mp4"" -vframes 1 ""test.jpg"""; + + string inputFilePath = @"test.mp4"; + string outputFilePath = @"test.jpg"; + TimeSpan timespan = TimeSpan.FromSeconds(20); + + IArgument argument = new GetThumbnailArgument(inputFilePath, outputFilePath, timespan); + argument.ComposeArgument(); + + Assert.That(argument.Argument.ToString() == expectedOutput, "{0} != {1}".FormatInvariant(argument.Argument, expectedOutput)); + } + + + } +} diff --git a/MediaToolkit src/MediaToolkit.Test/Features/GetThumbnailArgument.cs b/MediaToolkit src/MediaToolkit.Test/Features/GetThumbnailArgument.cs new file mode 100644 index 0000000..04330ad --- /dev/null +++ b/MediaToolkit src/MediaToolkit.Test/Features/GetThumbnailArgument.cs @@ -0,0 +1,32 @@ +using System; +using System.Text; +using MediaToolkit.Util; + +namespace MediaToolkit.Test.Features +{ + public class GetThumbnailArgument : IArgument + { + public GetThumbnailArgument(string inputFilePath, string outputFilePath, TimeSpan seekPosition) + { + this.Argument = new StringBuilder(); + InputFilePath = inputFilePath; + OutputFilePath = outputFilePath; + SeekPosition = seekPosition; + } + + public string InputFilePath { get; private set; } + public string OutputFilePath { get; private set; } + public TimeSpan SeekPosition { get; private set; } + + + public void ComposeArgument() + { + this.Argument.Append("-ss {0} ".FormatInvariant(this.SeekPosition.TotalSeconds)); + this.Argument.Append("-i \"{0}\" ".FormatInvariant(this.InputFilePath)); + this.Argument.Append("-vframes {0} ".FormatInvariant(1)); + this.Argument.Append("\"{0}\"".FormatInvariant(this.OutputFilePath)); + } + + public StringBuilder Argument { get; private set; } + } +} \ No newline at end of file diff --git a/MediaToolkit src/MediaToolkit.Test/Features/IArgument.cs b/MediaToolkit src/MediaToolkit.Test/Features/IArgument.cs new file mode 100644 index 0000000..7409439 --- /dev/null +++ b/MediaToolkit src/MediaToolkit.Test/Features/IArgument.cs @@ -0,0 +1,11 @@ +using System.Text; + +namespace MediaToolkit.Test.Features +{ + public interface IArgument + { + StringBuilder Argument { get; } + + void ComposeArgument(); + } +} \ No newline at end of file diff --git a/MediaToolkit src/MediaToolkit.Test/Features/IMediaProcessor.cs b/MediaToolkit src/MediaToolkit.Test/Features/IMediaProcessor.cs new file mode 100644 index 0000000..870c53b --- /dev/null +++ b/MediaToolkit src/MediaToolkit.Test/Features/IMediaProcessor.cs @@ -0,0 +1,12 @@ +namespace MediaToolkit.Test.Features +{ + /* + * This will eventually replace the "Engine" class + */ + + public interface IMediaProcessor where TArgument : IArgument + { + + + } +} \ No newline at end of file diff --git a/MediaToolkit src/MediaToolkit.Test/Features/MetadataTestsAndFeatures.cs b/MediaToolkit src/MediaToolkit.Test/Features/MetadataTestsAndFeatures.cs new file mode 100644 index 0000000..e1eafbb --- /dev/null +++ b/MediaToolkit src/MediaToolkit.Test/Features/MetadataTestsAndFeatures.cs @@ -0,0 +1,26 @@ +using System; +using System.Linq; +using MediaToolkit.Features; +using MediaToolkit.Util; +using NUnit.Framework; + +namespace MediaToolkit.Test.Features +{ + [TestFixture] + public class MetadataTestsAndFeatures + { + [Test] + public void Init() + { + MetadataProvider provider = new MetadataProvider(); + var meta = provider.GetMetadata( + @"../../TestVideo/BigBunny.m4v"); + + meta.MetadataIndex.Select(kvp => "{0}:{1}".FormatInvariant(kvp.Key, kvp.Value) ) + .ToList() + .ForEach(Console.WriteLine); + } + + + } +} \ No newline at end of file diff --git a/MediaToolkit src/MediaToolkit.Test/MediaToolkit.Test.csproj b/MediaToolkit src/MediaToolkit.Test/MediaToolkit.Test.csproj index 7acaa14..49789ff 100644 --- a/MediaToolkit src/MediaToolkit.Test/MediaToolkit.Test.csproj +++ b/MediaToolkit src/MediaToolkit.Test/MediaToolkit.Test.csproj @@ -47,6 +47,11 @@ + + + + + diff --git a/MediaToolkit src/MediaToolkit/EngineBase.cs b/MediaToolkit src/MediaToolkit/EngineBase.cs index e37357e..0251c5c 100644 --- a/MediaToolkit src/MediaToolkit/EngineBase.cs +++ b/MediaToolkit src/MediaToolkit/EngineBase.cs @@ -4,8 +4,6 @@ using System.Configuration; using System.Diagnostics; using System.IO; - using System.IO.Compression; - using System.Reflection; using System.Threading; using MediaToolkit.Properties; @@ -86,7 +84,7 @@ private void EnsureFFmpegFileExists() { if (!File.Exists(this.FFmpegFilePath)) { - UnpackFFmpegExecutable(this.FFmpegFilePath); + Document.Decompress(Resources.FFmpegManifestResourceName, this.FFmpegFilePath); } } @@ -111,27 +109,6 @@ private static void KillFFmpegProcesses() } } - ///------------------------------------------------------------------------------------------------- - /// Unpack ffmpeg executable. - /// Thrown when an exception error condition occurs. - private static void UnpackFFmpegExecutable(string path) - { - Stream compressedFFmpegStream = Assembly.GetExecutingAssembly() - .GetManifestResourceStream(Resources.FFmpegManifestResourceName); - - if (compressedFFmpegStream == null) - { - throw new Exception(Resources.Exceptions_Null_FFmpeg_Gzip_Stream); - } - - using (FileStream fileStream = new FileStream(path, FileMode.Create)) - using (GZipStream compressedStream = new GZipStream(compressedFFmpegStream, CompressionMode.Decompress)) - { - compressedStream.CopyTo(fileStream); - } - } - - ///------------------------------------------------------------------------------------------------- /// diff --git a/MediaToolkit src/MediaToolkit/Features/IMetadata.cs b/MediaToolkit src/MediaToolkit/Features/IMetadata.cs new file mode 100644 index 0000000..fe580d5 --- /dev/null +++ b/MediaToolkit src/MediaToolkit/Features/IMetadata.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace MediaToolkit.Features +{ + public interface IMetadata + { + Dictionary MetadataIndex { get; set; } + } +} \ No newline at end of file diff --git a/MediaToolkit src/MediaToolkit/Features/IMetadataProvider.cs b/MediaToolkit src/MediaToolkit/Features/IMetadataProvider.cs new file mode 100644 index 0000000..cc6f68a --- /dev/null +++ b/MediaToolkit src/MediaToolkit/Features/IMetadataProvider.cs @@ -0,0 +1,9 @@ +using System; + +namespace MediaToolkit.Features +{ + public interface IMetadataProvider : IDisposable + { + IMetadata GetMetadata(string filename); + } +} \ No newline at end of file diff --git a/MediaToolkit src/MediaToolkit/Features/Metadata.cs b/MediaToolkit src/MediaToolkit/Features/Metadata.cs new file mode 100644 index 0000000..92ca8cd --- /dev/null +++ b/MediaToolkit src/MediaToolkit/Features/Metadata.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace MediaToolkit.Features +{ + public class Metadata : IMetadata + { + public Dictionary MetadataIndex { get; set; } + } +} \ No newline at end of file diff --git a/MediaToolkit src/MediaToolkit/Features/MetadataProvider.cs b/MediaToolkit src/MediaToolkit/Features/MetadataProvider.cs new file mode 100644 index 0000000..e3b7317 --- /dev/null +++ b/MediaToolkit src/MediaToolkit/Features/MetadataProvider.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using MediaToolkit.Util; + +namespace MediaToolkit.Features +{ + public class MetadataProvider : IMetadataProvider + { + const string DefaultExiftoolPath = "/MediaToolkit/exiftool.exe"; + + public MetadataProvider() + { + Document.Decompress("MediaToolkit.Resources.Exiftool.exe.gz", DefaultExiftoolPath); + + this.isDisposed = false; + this.exiftoolProcess = new Process(); + } + + private bool isDisposed; + + private readonly Process exiftoolProcess; + + protected virtual void Dispose(bool isDisposing) + { + if (!isDisposing) return; + if (this.isDisposed) return; + + this.isDisposed = true; + this.exiftoolProcess.Dispose(); + GC.SuppressFinalize(this); + } + + public void Dispose() + { + this.Dispose(true); + } + + public IMetadata GetMetadata(string filename) + { + exiftoolProcess.StartInfo = new ProcessStartInfo + { + Arguments = "\"{0}\"".FormatInvariant(filename), + FileName = DefaultExiftoolPath, + CreateNoWindow = true, + RedirectStandardInput = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + WindowStyle = ProcessWindowStyle.Hidden + }; + + Dictionary metadataIndex = new Dictionary(); + + exiftoolProcess.OutputDataReceived += (sender, args) => + { + if (args.Data.Contains("ExifTool Version Number")) return; + + var keyValue = args.Data.Split(':'); + metadataIndex.Add(keyValue[0], keyValue[1]); + }; + + exiftoolProcess.Start(); + exiftoolProcess.BeginOutputReadLine(); + exiftoolProcess.WaitForExit(); + + return new Metadata {MetadataIndex = metadataIndex}; + } + } +} \ No newline at end of file diff --git a/MediaToolkit src/MediaToolkit/MediaToolkit.csproj b/MediaToolkit src/MediaToolkit/MediaToolkit.csproj index bb48040..4d99340 100644 --- a/MediaToolkit src/MediaToolkit/MediaToolkit.csproj +++ b/MediaToolkit src/MediaToolkit/MediaToolkit.csproj @@ -1,4 +1,4 @@ - + @@ -9,7 +9,7 @@ Properties MediaToolkit MediaToolkit - v2.0 + v4.0 512 AssemblyVersionAttribute @@ -64,6 +64,10 @@ + + + + @@ -86,8 +90,10 @@ Resources.Designer.cs Designer + + - + \ No newline at end of file diff --git a/MediaToolkit src/MediaToolkit/Properties/AssemblyInfo.cs b/MediaToolkit src/MediaToolkit/Properties/AssemblyInfo.cs index e96ffdd..e708f99 100644 --- a/MediaToolkit src/MediaToolkit/Properties/AssemblyInfo.cs +++ b/MediaToolkit src/MediaToolkit/Properties/AssemblyInfo.cs @@ -11,9 +11,9 @@ [assembly: AssemblyCompany("Aydin")] [assembly: AssemblyCopyright("Copyright © 2014")] [assembly: AssemblyDescription("A .NET wrapper for FFmpeg, to convert & process all types of media.")] -[assembly: AssemblyFileVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.1")] [assembly: AssemblyProduct("MediaToolkit")] [assembly: AssemblyTitle("MediaToolkit")] -[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyVersion("1.1.0.1")] [assembly: ComVisible(false)] [assembly: Guid("e03e0a90-f6c1-4d13-8649-d61783abeff3")] diff --git a/MediaToolkit src/MediaToolkit/Properties/Resources.Designer.cs b/MediaToolkit src/MediaToolkit/Properties/Resources.Designer.cs index a4ca44f..c5d5b3b 100644 --- a/MediaToolkit src/MediaToolkit/Properties/Resources.Designer.cs +++ b/MediaToolkit src/MediaToolkit/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.0 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -79,11 +79,11 @@ internal static string Exceptions_FFmpeg_Process_Not_Running { } /// - /// Looks up a localized string similar to FFMpeg GZip stream is null. + /// Looks up a localized string similar to Compressed resource stream is null. /// - internal static string Exceptions_Null_FFmpeg_Gzip_Stream { + internal static string Exceptions_Null_CompressedResourceStream { get { - return ResourceManager.GetString("Exceptions_Null_FFmpeg_Gzip_Stream", resourceCulture); + return ResourceManager.GetString("Exceptions_Null_CompressedResourceStream", resourceCulture); } } diff --git a/MediaToolkit src/MediaToolkit/Properties/Resources.resx b/MediaToolkit src/MediaToolkit/Properties/Resources.resx index 2474dee..d685b73 100644 --- a/MediaToolkit src/MediaToolkit/Properties/Resources.resx +++ b/MediaToolkit src/MediaToolkit/Properties/Resources.resx @@ -1,108 +1,108 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + MediaToolkit.Resources.FFmpeg.exe.gz - - FFMpeg GZip stream is null + + Compressed resource stream is null FFmpeg process is not running. diff --git a/MediaToolkit src/MediaToolkit/Resources/Exiftool.exe.gz b/MediaToolkit src/MediaToolkit/Resources/Exiftool.exe.gz new file mode 100644 index 0000000..7482fcb Binary files /dev/null and b/MediaToolkit src/MediaToolkit/Resources/Exiftool.exe.gz differ diff --git a/MediaToolkit src/MediaToolkit/Resources/FFmpeg.exe.gz b/MediaToolkit src/MediaToolkit/Resources/FFmpeg.exe.gz index 99f3ba1..c789e17 100644 Binary files a/MediaToolkit src/MediaToolkit/Resources/FFmpeg.exe.gz and b/MediaToolkit src/MediaToolkit/Resources/FFmpeg.exe.gz differ diff --git a/MediaToolkit src/MediaToolkit/Util/Document.cs b/MediaToolkit src/MediaToolkit/Util/Document.cs index c2b333a..70bd02d 100644 --- a/MediaToolkit src/MediaToolkit/Util/Document.cs +++ b/MediaToolkit src/MediaToolkit/Util/Document.cs @@ -1,4 +1,7 @@ using System.IO; +using System.IO.Compression; +using System.Reflection; +using MediaToolkit.Properties; namespace MediaToolkit.Util { @@ -55,6 +58,31 @@ internal static bool IsLocked(string filePath) return false; } + public static void Decompress(string resource, string toPath) + { + if (resource.IsNullOrWhiteSpace()) + { + throw new ArgumentNullException("resource"); + } + + if (toPath.IsNullOrWhiteSpace()) + { + throw new ArgumentNullException("toPath"); + } + + Stream compressedResourceStream = Assembly.GetExecutingAssembly() + .GetManifestResourceStream(resource); + if (compressedResourceStream == null) + { + throw new Exception(Resources.Exceptions_Null_CompressedResourceStream); + } + + using (FileStream fileStream = new FileStream(toPath, FileMode.Create)) + using (GZipStream compressedStream = new GZipStream(compressedResourceStream, CompressionMode.Decompress)) + { + compressedStream.CopyTo(fileStream); + } + } } } \ No newline at end of file