From 399ab292d7feddf5e83be866caafbaef634eca87 Mon Sep 17 00:00:00 2001 From: sr55 Date: Sun, 12 Jun 2011 16:54:23 +0000 Subject: WinGui: Bring in the HandBrake Interop library written by RandomEngy. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4045 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- .../HandBrakeInterop.Test/EncodeJobsPersist.cs | 30 + .../HandBrakeInterop.Test.csproj | 68 + .../Properties/AssemblyInfo.cs | 35 + .../HandBrakeInterop.Test/TestEncodes.cs | 100 ++ .../TestFiles/Jobs/Normal.xml | Bin 0 -> 5250 bytes win/CS/HandBrake.Interop/HandBrakeInterop.sln | 42 + win/CS/HandBrake.Interop/HandBrakeInterop.suo | Bin 0 -> 37888 bytes win/CS/HandBrake.Interop/HandBrakeInterop.vsmdi | 6 + .../HandBrakeInterop/Converters.cs | 110 ++ .../HandBrakeInterop/EncodeCompletedEventArgs.cs | 12 + .../HandBrakeInterop/EncodeProgressEventArgs.cs | 20 + .../HandBrakeInterop/HandBrakeInstance.cs | 1600 ++++++++++++++++++++ .../HandBrakeInterop/HandBrakeInterop.csproj | 206 +++ .../HandBrakeInterop/HandBrakeUtils.cs | 254 ++++ .../HandBrakeInterop/HbLib/HbFunctions.cs | 237 +++ .../HandBrakeInterop/HbLib/Misc.cs | 415 +++++ .../HandBrakeInterop/HbLib/NativeConstants.cs | 99 ++ .../HandBrakeInterop/HbLib/hb_audio.cs | 120 ++ .../HandBrakeInterop/HbLib/hb_chapter_s.cs | 48 + .../HandBrakeInterop/HbLib/hb_handle_s.cs | 78 + .../HandBrakeInterop/HbLib/hb_job_s.cs | 149 ++ .../HandBrakeInterop/HbLib/hb_subtitle.cs | 122 ++ .../HandBrakeInterop/HbLib/hb_title_s.cs | 145 ++ .../HandBrakeInterop/InteropUtilities.cs | 144 ++ .../HandBrake.Interop/HandBrakeInterop/Language.cs | 38 + .../HandBrakeInterop/LanguageCodes.cs | 255 ++++ .../HandBrakeInterop/MarshalingConstants.cs | 18 + .../HandBrakeInterop/MessageLoggedEventArgs.cs | 12 + .../HandBrakeInterop/Model/Cropping.cs | 26 + .../HandBrakeInterop/Model/EncodeJob.cs | 83 + .../HandBrakeInterop/Model/Encoding/Anamorphic.cs | 20 + .../Model/Encoding/AudioEncoder.cs | 32 + .../Model/Encoding/AudioEncoding.cs | 34 + .../HandBrakeInterop/Model/Encoding/Decomb.cs | 14 + .../HandBrakeInterop/Model/Encoding/Deinterlace.cs | 16 + .../HandBrakeInterop/Model/Encoding/Denoise.cs | 16 + .../HandBrakeInterop/Model/Encoding/Detelecine.cs | 14 + .../Model/Encoding/EncodingProfile.cs | 113 ++ .../HandBrakeInterop/Model/Encoding/Mixdown.cs | 29 + .../Model/Encoding/OutputExtension.cs | 13 + .../Model/Encoding/OutputFormat.cs | 17 + .../Model/Encoding/VideoEncodeRateType.cs | 14 + .../Model/Encoding/VideoEncoder.cs | 20 + .../HandBrakeInterop/Model/Limits.cs | 14 + .../HandBrakeInterop/Model/Size.cs | 19 + .../HandBrakeInterop/Model/SourceSubtitle.cs | 29 + .../HandBrakeInterop/Model/SourceType.cs | 10 + .../HandBrakeInterop/Model/SrtSubtitle.cs | 28 + .../HandBrakeInterop/Model/Subtitles.cs | 13 + .../HandBrakeInterop/Model/VideoRangeType.cs | 20 + .../HandBrakeInterop/NativeList.cs | 34 + .../HandBrakeInterop/Properties/AssemblyInfo.cs | 36 + .../HandBrakeInterop/ScanProgressEventArgs.cs | 13 + .../HandBrakeInterop/SourceData/AudioCodec.cs | 17 + .../HandBrakeInterop/SourceData/AudioTrack.cs | 90 ++ .../HandBrakeInterop/SourceData/Chapter.cs | 38 + .../HandBrakeInterop/SourceData/InputType.cs | 20 + .../HandBrakeInterop/SourceData/Subtitle.cs | 54 + .../HandBrakeInterop/SourceData/SubtitleSource.cs | 18 + .../HandBrakeInterop/SourceData/SubtitleType.cs | 13 + .../HandBrakeInterop/SourceData/Title.cs | 144 ++ .../HandBrakeInterop/Utilities.cs | 32 + .../HandBrakeInterop/libgcc_s_sjlj-1.dll | Bin 0 -> 241655 bytes win/CS/HandBrake.Interop/Local.testsettings | 20 + win/CS/HandBrake10.sln | 28 + 65 files changed, 5514 insertions(+) create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop.Test/EncodeJobsPersist.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop.Test/HandBrakeInterop.Test.csproj create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop.Test/Properties/AssemblyInfo.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop.Test/TestEncodes.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop.Test/TestFiles/Jobs/Normal.xml create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop.sln create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop.suo create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop.vsmdi create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Converters.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/EncodeCompletedEventArgs.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/EncodeProgressEventArgs.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInstance.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInterop.csproj create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeUtils.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/HbFunctions.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/Misc.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/NativeConstants.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_audio.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_chapter_s.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_handle_s.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_job_s.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_subtitle.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_title_s.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/InteropUtilities.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Language.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/LanguageCodes.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/MarshalingConstants.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/MessageLoggedEventArgs.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Cropping.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/EncodeJob.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Anamorphic.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoder.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoding.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Decomb.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Deinterlace.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Denoise.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Detelecine.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/EncodingProfile.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Mixdown.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/OutputExtension.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/OutputFormat.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/VideoEncodeRateType.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/VideoEncoder.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Limits.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Size.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/SourceSubtitle.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/SourceType.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/SrtSubtitle.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Subtitles.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/VideoRangeType.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/NativeList.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Properties/AssemblyInfo.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/ScanProgressEventArgs.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/AudioCodec.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/AudioTrack.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/Chapter.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/InputType.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/Subtitle.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/SubtitleSource.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/SubtitleType.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/Title.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Utilities.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/libgcc_s_sjlj-1.dll create mode 100644 win/CS/HandBrake.Interop/Local.testsettings (limited to 'win') diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop.Test/EncodeJobsPersist.cs b/win/CS/HandBrake.Interop/HandBrakeInterop.Test/EncodeJobsPersist.cs new file mode 100644 index 000000000..5ede69963 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop.Test/EncodeJobsPersist.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using HandBrake.Interop; + +namespace HandBrakeInterop.Test +{ + public static class EncodeJobsPersist + { + private static XmlSerializer xmlSerializer = new XmlSerializer(typeof(EncodeJob)); + + public static EncodeJob GetJob(string jobName) + { + XDocument doc = XDocument.Load(jobName + ".xml"); + using (XmlReader reader = doc.CreateReader()) + { + var job = xmlSerializer.Deserialize(reader) as EncodeJob; + + + + return job; + } + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop.Test/HandBrakeInterop.Test.csproj b/win/CS/HandBrake.Interop/HandBrakeInterop.Test/HandBrakeInterop.Test.csproj new file mode 100644 index 000000000..5b7a8b72c --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop.Test/HandBrakeInterop.Test.csproj @@ -0,0 +1,68 @@ + + + + Debug + AnyCPU + + + 2.0 + {D721824C-CAFA-40B1-83C9-83E4B1215D60} + Library + Properties + HandBrakeInterop.Test + HandBrakeInterop.Test + v4.0 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + 3.5 + + + + + + + False + + + + + + + + + + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1} + HandBrakeInterop + + + + + \ No newline at end of file diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop.Test/Properties/AssemblyInfo.cs b/win/CS/HandBrake.Interop/HandBrakeInterop.Test/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..2352dc269 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop.Test/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("HandBrakeInterop.Test")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("HandBrakeInterop.Test")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("2731c894-c1fc-4690-9557-aa56591b17ab")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop.Test/TestEncodes.cs b/win/CS/HandBrake.Interop/HandBrakeInterop.Test/TestEncodes.cs new file mode 100644 index 000000000..cb5a848eb --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop.Test/TestEncodes.cs @@ -0,0 +1,100 @@ +using System; +using System.IO; +using System.Text; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using HandBrake.Interop; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace HandBrakeInterop.Test +{ + [TestClass] + public class TestEncodes + { + public const string OutputVideoDirectoryName = "OutputVideos"; + private static readonly string OutputVideoDirectory = Path.Combine(Environment.CurrentDirectory, OutputVideoDirectoryName); + + private ManualResetEvent resetEvent = new ManualResetEvent(false); + + [ClassInitialize] + public static void Init(TestContext context) + { + EnsureOutputVideoDirectoryExists(); + + FileInfo[] files = new DirectoryInfo(OutputVideoDirectory).GetFiles(); + foreach (FileInfo file in files) + { + file.Delete(); + } + } + + [TestMethod] + public void Normal() + { + this.RunJob("Normal"); + } + + private void RunJob(string jobName) + { + this.resetEvent.Reset(); + + EncodeJob job = EncodeJobsPersist.GetJob("Normal"); + + if (job.SourceType == SourceType.VideoFolder) + { + job.SourcePath = Path.Combine(Environment.CurrentDirectory, Path.GetFileName(job.SourcePath)); + } + + if (job.SourceType == SourceType.File) + { + job.SourcePath = Path.Combine(Environment.CurrentDirectory, Path.GetFileName(job.SourcePath)); + } + + string extension; + if (job.EncodingProfile.OutputFormat == OutputFormat.Mkv) + { + extension = ".mkv"; + } + else + { + extension = ".mp4"; + } + + job.OutputPath = Path.Combine(OutputVideoDirectory, jobName + extension); + + var instance = new HandBrakeInstance(); + instance.Initialize(0); + instance.ScanCompleted += (sender, e) => + { + this.resetEvent.Set(); + }; + + instance.StartScan(job.SourcePath, 10); + this.resetEvent.WaitOne(); + + this.resetEvent.Reset(); + instance.EncodeCompleted += (sender, e) => + { + Assert.IsFalse(e.Error); + this.resetEvent.Set(); + }; + + instance.StartEncode(job); + this.resetEvent.WaitOne(); + + Assert.IsTrue(File.Exists(job.OutputPath)); + + var fileInfo = new FileInfo(job.OutputPath); + Assert.IsTrue(fileInfo.Length > 1024); + } + + private static void EnsureOutputVideoDirectoryExists() + { + if (!Directory.Exists(OutputVideoDirectory)) + { + Directory.CreateDirectory(OutputVideoDirectory); + } + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop.Test/TestFiles/Jobs/Normal.xml b/win/CS/HandBrake.Interop/HandBrakeInterop.Test/TestFiles/Jobs/Normal.xml new file mode 100644 index 000000000..b717a7c36 Binary files /dev/null and b/win/CS/HandBrake.Interop/HandBrakeInterop.Test/TestFiles/Jobs/Normal.xml differ diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop.sln b/win/CS/HandBrake.Interop/HandBrakeInterop.sln new file mode 100644 index 000000000..5973725a9 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop.sln @@ -0,0 +1,42 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandBrakeInterop", "HandBrakeInterop\HandBrakeInterop.csproj", "{F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandBrakeInterop.Test", "HandBrakeInterop.Test\HandBrakeInterop.Test.csproj", "{D721824C-CAFA-40B1-83C9-83E4B1215D60}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F9A6B796-8476-4F7D-BD4E-A1B73A42E2F7}" + ProjectSection(SolutionItems) = preProject + HandBrakeInterop.vsmdi = HandBrakeInterop.vsmdi + Local.testsettings = Local.testsettings + EndProjectSection +EndProject +Global + GlobalSection(TestCaseManagementSettings) = postSolution + CategoryFile = HandBrakeInterop.vsmdi + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|x64.ActiveCfg = Debug|x64 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|x64.Build.0 = Debug|x64 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|x86.ActiveCfg = Debug|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|x86.Build.0 = Debug|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|x64.ActiveCfg = Release|x64 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|x64.Build.0 = Release|x64 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|x86.ActiveCfg = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|x86.Build.0 = Release|x86 + {D721824C-CAFA-40B1-83C9-83E4B1215D60}.Debug|x64.ActiveCfg = Debug|Any CPU + {D721824C-CAFA-40B1-83C9-83E4B1215D60}.Debug|x64.Build.0 = Debug|Any CPU + {D721824C-CAFA-40B1-83C9-83E4B1215D60}.Debug|x86.ActiveCfg = Debug|Any CPU + {D721824C-CAFA-40B1-83C9-83E4B1215D60}.Release|x64.ActiveCfg = Release|Any CPU + {D721824C-CAFA-40B1-83C9-83E4B1215D60}.Release|x86.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop.suo b/win/CS/HandBrake.Interop/HandBrakeInterop.suo new file mode 100644 index 000000000..471ae0612 Binary files /dev/null and b/win/CS/HandBrake.Interop/HandBrakeInterop.suo differ diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop.vsmdi b/win/CS/HandBrake.Interop/HandBrakeInterop.vsmdi new file mode 100644 index 000000000..bbe274502 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop.vsmdi @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Converters.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Converters.cs new file mode 100644 index 000000000..691c97701 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Converters.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using HandBrake.SourceData; + +namespace HandBrake.Interop +{ + public static class Converters + { + private static Dictionary vrates = new Dictionary + { + {5, 5400000}, + {10, 2700000}, + {12, 2250000}, + {15, 1800000}, + {23.976, 1126125}, + {24, 1125000}, + {25, 1080000}, + {29.97, 900900} + }; + + public static int FramerateToVrate(double framerate) + { + if (!vrates.ContainsKey(framerate)) + { + throw new ArgumentException("Framerate not recognized.", "framerate"); + } + + return vrates[framerate]; + } + + public static int MixdownToNative(Mixdown mixdown) + { + if (mixdown == Mixdown.Auto) + { + throw new ArgumentException("Cannot convert Auto to native."); + } + + switch (mixdown) + { + case Mixdown.DolbyProLogicII: + return NativeConstants.HB_AMIXDOWN_DOLBYPLII; + case Mixdown.DolbySurround: + return NativeConstants.HB_AMIXDOWN_DOLBY; + case Mixdown.Mono: + return NativeConstants.HB_AMIXDOWN_MONO; + case Mixdown.SixChannelDiscrete: + return NativeConstants.HB_AMIXDOWN_6CH; + case Mixdown.Stereo: + return NativeConstants.HB_AMIXDOWN_STEREO; + } + + return 0; + } + + public static Mixdown NativeToMixdown(int mixdown) + { + switch (mixdown) + { + case NativeConstants.HB_AMIXDOWN_MONO: + return Mixdown.Mono; + case NativeConstants.HB_AMIXDOWN_STEREO: + return Mixdown.Stereo; + case NativeConstants.HB_AMIXDOWN_DOLBY: + return Mixdown.DolbySurround; + case NativeConstants.HB_AMIXDOWN_DOLBYPLII: + return Mixdown.DolbyProLogicII; + case NativeConstants.HB_AMIXDOWN_6CH: + return Mixdown.SixChannelDiscrete; + } + + throw new ArgumentException("Unrecognized mixdown: " + mixdown, "mixdown"); + } + + public static uint AudioEncoderToNative(AudioEncoder encoder) + { + switch (encoder) + { + case AudioEncoder.Ac3Passthrough: + return NativeConstants.HB_ACODEC_AC3_PASS; + case AudioEncoder.DtsPassthrough: + return NativeConstants.HB_ACODEC_DCA_PASS; + case AudioEncoder.Faac: + return NativeConstants.HB_ACODEC_FAAC; + case AudioEncoder.Lame: + return NativeConstants.HB_ACODEC_LAME; + case AudioEncoder.Ac3: + return NativeConstants.HB_ACODEC_AC3; + case AudioEncoder.Vorbis: + return NativeConstants.HB_ACODEC_VORBIS; + } + + return 0; + } + + public static AudioCodec NativeToAudioCodec(uint codec) + { + switch (codec) + { + case NativeConstants.HB_ACODEC_AC3: + return AudioCodec.Ac3; + case NativeConstants.HB_ACODEC_DCA: + return AudioCodec.Dts; + default: + return AudioCodec.Other; + } + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/EncodeCompletedEventArgs.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/EncodeCompletedEventArgs.cs new file mode 100644 index 000000000..f35a449a1 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/EncodeCompletedEventArgs.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public class EncodeCompletedEventArgs : EventArgs + { + public bool Error { get; set; } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/EncodeProgressEventArgs.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/EncodeProgressEventArgs.cs new file mode 100644 index 000000000..484ea7b7b --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/EncodeProgressEventArgs.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public class EncodeProgressEventArgs : EventArgs + { + public float FractionComplete { get; set; } + public float CurrentFrameRate { get; set; } + public float AverageFrameRate { get; set; } + public TimeSpan EstimatedTimeLeft { get; set; } + + /// + /// Gets or sets the current encoding pass. (-1: subtitle scan, 1: first pass, 2: second pass) + /// + public int Pass { get; set; } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInstance.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInstance.cs new file mode 100644 index 000000000..1d8d63a2e --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInstance.cs @@ -0,0 +1,1600 @@ +namespace HandBrake.Interop +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Runtime.InteropServices; + using System.Text; + using System.Timers; + using System.Threading; + using System.Windows.Media.Imaging; + using HandBrake.SourceData; + using HandBrake.Interop; + + /// + /// A wrapper for a HandBrake instance. + /// + public class HandBrakeInstance : IDisposable + { + /// + /// The modulus for picture size when auto-sizing dimensions. + /// + private const int PictureAutoSizeModulus = 2; + + /// + /// Modulus used for picture size when using non-anamorphic. + /// + private const int NonAnamorphicAutoSizeModulus = 16; + + /// + /// The number of MS between status polls when scanning. + /// + private const double ScanPollIntervalMs = 200; + + /// + /// The number of MS between status polls when encoding. + /// + private const double EncodePollIntervalMs = 200; + + /// + /// X264 options to add for a turbo first pass. + /// + private const string TurboX264Opts = "ref=1:subme=2:me=dia:analyse=none:trellis=0:no-fast-pskip=0:8x8dct=0:weightb=0"; + + /// + /// Default value to give as a minimum duration when scanning. + /// + private const ulong DefaultMinDuration = 900000; + + /// + /// The native handle to the HandBrake instance. + /// + private IntPtr hbHandle; + + /// + /// The number of previews created during scan. + /// + private int previewCount; + + /// + /// The timer to poll for scan status. + /// + private System.Timers.Timer scanPollTimer; + + /// + /// The timer to poll for encode status. + /// + private System.Timers.Timer encodePollTimer; + + /// + /// The list of original titles in native structure form. + /// + private List originalTitles; + + /// + /// The list of titles on this instance. + /// + private List titles; + + /// <summary> + /// The current encode job for this instance. + /// </summary> + private EncodeJob currentJob; + + /// <summary> + /// True if the current job is scanning for subtitles. + /// </summary> + private bool subtitleScan; + + /// <summary> + /// The index of the default title. + /// </summary> + private int featureTitle; + + /// <summary> + /// A list of native memory locations allocated by this instance. + /// </summary> + private List<IntPtr> encodeAllocatedMemory; + + /// <summary> + /// Fires for progress updates when scanning. + /// </summary> + public event EventHandler<ScanProgressEventArgs> ScanProgress; + + /// <summary> + /// Fires when a scan has completed. + /// </summary> + public event EventHandler<EventArgs> ScanCompleted; + + /// <summary> + /// Fires for progress updates when encoding. + /// </summary> + public event EventHandler<EncodeProgressEventArgs> EncodeProgress; + + /// <summary> + /// Fires when an encode has completed. + /// </summary> + public event EventHandler<EncodeCompletedEventArgs> EncodeCompleted; + + /// <summary> + /// Destructor. + /// </summary> + ~HandBrakeInstance() + { + this.Dispose(false); + } + + /// <summary> + /// The list of titles on this instance. + /// </summary> + public List<Title> Titles + { + get + { + return this.titles; + } + } + + /// <summary> + /// The number of previews created during scan. + /// </summary> + public int PreviewCount + { + get + { + return this.previewCount; + } + } + + /// <summary> + /// Gets the index of the default title. + /// </summary> + public int FeatureTitle + { + get + { + return this.featureTitle; + } + } + + /// <summary> + /// Initializes this instance. + /// </summary> + /// <param name="verbosity"></param> + public void Initialize(int verbosity) + { + HandBrakeUtils.RegisterLogger(); + this.hbHandle = HBFunctions.hb_init(verbosity, update_check: 0); + } + + /// <summary> + /// Starts scanning the given path. + /// </summary> + /// <param name="path">The path to the video to scan.</param> + /// <param name="previewCount">The number of preview images to make.</param> + public void StartScan(string path, int previewCount) + { + this.StartScan(path, previewCount, 0); + } + + /// <summary> + /// Starts a scan of the given path. + /// </summary> + /// <param name="path">The path of the video to scan.</param> + /// <param name="previewCount">The number of previews to make on each title.</param> + /// <param name="titleIndex">The title index to scan (1-based, 0 for all titles).</param> + public void StartScan(string path, int previewCount, int titleIndex) + { + this.previewCount = previewCount; + HBFunctions.hb_scan(this.hbHandle, path, titleIndex, previewCount, 1, DefaultMinDuration); + this.scanPollTimer = new System.Timers.Timer(); + this.scanPollTimer.Interval = ScanPollIntervalMs; + + // Lambda notation used to make sure we can view any JIT exceptions the method throws + this.scanPollTimer.Elapsed += (o, e) => + { + this.PollScanProgress(); + }; + this.scanPollTimer.Start(); + } + + /// <summary> + /// Stops an ongoing scan. + /// </summary> + public void StopScan() + { + HBFunctions.hb_scan_stop(this.hbHandle); + } + + /// <summary> + /// Gets an image for the given job and preview + /// </summary> + /// <remarks> + /// Only incorporates sizing and aspect ratio into preview image. + /// </remarks> + /// <param name="job">The encode job to preview.</param> + /// <param name="previewNumber">The index of the preview to get (0-based).</param> + /// <returns>An image with the requested preview.</returns> + public BitmapImage GetPreview(EncodeJob job, int previewNumber) + { + hb_title_s title = this.GetOriginalTitle(job.Title); + + hb_job_s nativeJob = InteropUtilities.ReadStructure<hb_job_s>(title.job); + List<IntPtr> allocatedMemory = this.ApplyJob(ref nativeJob, job); + + // There are some problems with getting previews with deinterlacing. Disabling for now. + nativeJob.deinterlace = 0; + + // Create a new job pointer from our modified job object + IntPtr newJob = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(hb_job_s))); + Marshal.StructureToPtr(nativeJob, newJob, false); + allocatedMemory.Add(newJob); + + int outputWidth = nativeJob.width; + int outputHeight = nativeJob.height; + int imageBufferSize = outputWidth * outputHeight * 4; + IntPtr nativeBuffer = Marshal.AllocHGlobal(imageBufferSize); + allocatedMemory.Add(nativeBuffer); + HBFunctions.hb_set_job(this.hbHandle, job.Title, ref nativeJob); + HBFunctions.hb_get_preview_by_index(this.hbHandle, job.Title, previewNumber, nativeBuffer); + + // Copy the filled image buffer to a managed array. + byte[] managedBuffer = new byte[imageBufferSize]; + Marshal.Copy(nativeBuffer, managedBuffer, 0, imageBufferSize); + + InteropUtilities.FreeMemory(allocatedMemory); + + var bitmap = new System.Drawing.Bitmap(outputWidth, outputHeight); + System.Drawing.Imaging.BitmapData bitmapData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, outputWidth, outputHeight), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb); + + IntPtr ptr = bitmapData.Scan0; + + for (int i = 0; i < nativeJob.height; i++) + { + Marshal.Copy(managedBuffer, i * nativeJob.width * 4, ptr, nativeJob.width * 4); + ptr = IntPtr.Add(ptr, bitmapData.Stride); + } + + bitmap.UnlockBits(bitmapData); + + using (var memoryStream = new MemoryStream()) + { + try + { + bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Bmp); + } + finally + { + bitmap.Dispose(); + } + + var wpfBitmap = new BitmapImage(); + wpfBitmap.BeginInit(); + wpfBitmap.CacheOption = BitmapCacheOption.OnLoad; + wpfBitmap.StreamSource = memoryStream; + wpfBitmap.EndInit(); + wpfBitmap.Freeze(); + + return wpfBitmap; + } + } + + /// <summary> + /// Calculates the video bitrate for the given job and target size. + /// </summary> + /// <param name="job">The encode job.</param> + /// <param name="sizeMB">The target size in MB.</param> + /// <param name="overallSelectedLengthSeconds">The currently selected encode length. Used in preview + /// for calculating bitrate when the target size would be wrong.</param> + /// <returns>The video bitrate in kbps.</returns> + public int CalculateBitrate(EncodeJob job, int sizeMB, double overallSelectedLengthSeconds = 0) + { + long availableBytes = ((long) sizeMB) * 1024 * 1024; + + EncodingProfile profile = job.EncodingProfile; + Title title = this.GetTitle(job.Title); + + double lengthSeconds = overallSelectedLengthSeconds > 0 ? overallSelectedLengthSeconds : HandBrakeUtils.GetJobLengthSeconds(job, title); + lengthSeconds += 1.5; + + double outputFramerate; + if (profile.Framerate == 0) + { + outputFramerate = title.Framerate; + } + else + { + // Not sure what to do for VFR here hb_calc_bitrate never handled it... + // just use the peak for now. + outputFramerate = profile.Framerate; + } + + long frames = (long)(lengthSeconds * outputFramerate); + + availableBytes -= frames * HandBrakeUtils.ContainerOverheadPerFrame; + + List<Tuple<AudioEncoding, int>> outputTrackList = this.GetOutputTracks(job, title); + availableBytes -= HandBrakeUtils.GetAudioSize(job, lengthSeconds, title, outputTrackList); + + if (availableBytes < 0) + { + return 0; + } + + // Video bitrate is in kilobits per second, or where 1 kbps is 1000 bits per second. + // So 1 kbps is 125 bytes per second. + return (int)(availableBytes / (125 * lengthSeconds)); + } + + /// <summary> + /// Gives estimated file size (in MB) of the given job and video bitrate. + /// </summary> + /// <param name="job">The encode job.</param> + /// <param name="videoBitrate">The video bitrate to be used (kbps).</param> + /// <returns>The estimated file size (in MB) of the given job and video bitrate.</returns> + public double CalculateFileSize(EncodeJob job, int videoBitrate) + { + long totalBytes = 0; + + EncodingProfile profile = job.EncodingProfile; + Title title = this.GetTitle(job.Title); + + double lengthSeconds = HandBrakeUtils.GetJobLengthSeconds(job, title); + lengthSeconds += 1.5; + + double outputFramerate; + if (profile.Framerate == 0) + { + outputFramerate = title.Framerate; + } + else + { + // Not sure what to do for VFR here hb_calc_bitrate never handled it... + // just use the peak for now. + outputFramerate = profile.Framerate; + } + + long frames = (long)(lengthSeconds * outputFramerate); + + totalBytes += (long)(lengthSeconds * videoBitrate * 125); + totalBytes += frames * HandBrakeUtils.ContainerOverheadPerFrame; + + List<Tuple<AudioEncoding, int>> outputTrackList = this.GetOutputTracks(job, title); + totalBytes += HandBrakeUtils.GetAudioSize(job, lengthSeconds, title, outputTrackList); + + return (double)totalBytes / 1024 / 1024; + } + + /// <summary> + /// Starts an encode with the given job. + /// </summary> + /// <param name="jobToStart">The job to start.</param> + public void StartEncode(EncodeJob jobToStart) + { + this.StartEncode(jobToStart, false, 0, 0, 0); + } + + /// <summary> + /// Starts an encode with the given job. + /// </summary> + /// <param name="job">The job to start.</param> + /// <param name="preview">True if this is a preview encode.</param> + /// <param name="previewNumber">The preview number to start the encode at (0-based).</param> + /// <param name="previewSeconds">The number of seconds in the preview.</param> + /// <param name="overallSelectedLengthSeconds">The currently selected encode length. Used in preview + /// for calculating bitrate when the target size would be wrong.</param> + public void StartEncode(EncodeJob job, bool preview, int previewNumber, int previewSeconds, double overallSelectedLengthSeconds) + { + this.currentJob = job; + hb_job_s nativeJob = InteropUtilities.ReadStructure<hb_job_s>(this.GetOriginalTitle(job.Title).job); + this.encodeAllocatedMemory = this.ApplyJob(ref nativeJob, job, preview, previewNumber, previewSeconds, overallSelectedLengthSeconds); + + if (!preview && job.EncodingProfile.IncludeChapterMarkers) + { + Title title = this.GetTitle(job.Title); + int numChapters = title.Chapters.Count; + + if (job.UseDefaultChapterNames) + { + for (int i = 0; i < numChapters; i++) + { + HBFunctions.hb_set_chapter_name(this.hbHandle, job.Title, i + 1, "Chapter " + (i + 1)); + } + } + else + { + for (int i = 0; i < numChapters; i++) + { + HBFunctions.hb_set_chapter_name(this.hbHandle, job.Title, i + 1, job.CustomChapterNames[i]); + } + } + } + + this.subtitleScan = false; + if (job.Subtitles.SourceSubtitles != null) + { + foreach (SourceSubtitle subtitle in job.Subtitles.SourceSubtitles) + { + if (subtitle.TrackNumber == 0) + { + this.subtitleScan = true; + break; + } + } + } + + string x264Options = job.EncodingProfile.X264Options ?? string.Empty; + IntPtr originalX264Options = Marshal.StringToHGlobalAnsi(x264Options); + this.encodeAllocatedMemory.Add(originalX264Options); + + if (this.subtitleScan) + { + // If we need to scan subtitles, enqueue a pre-processing job to do that. + nativeJob.pass = -1; + nativeJob.indepth_scan = 1; + + nativeJob.advanced_opts = IntPtr.Zero; + + HBFunctions.hb_add(this.hbHandle, ref nativeJob); + } + + nativeJob.indepth_scan = 0; + + if (job.EncodingProfile.TwoPass) + { + // First pass. Apply turbo options if needed. + nativeJob.pass = 1; + string firstPassAdvancedOptions = x264Options; + if (job.EncodingProfile.TurboFirstPass) + { + if (firstPassAdvancedOptions == string.Empty) + { + firstPassAdvancedOptions = TurboX264Opts; + } + else + { + firstPassAdvancedOptions += ":" + TurboX264Opts; + } + } + + nativeJob.advanced_opts = Marshal.StringToHGlobalAnsi(firstPassAdvancedOptions); + this.encodeAllocatedMemory.Add(nativeJob.advanced_opts); + + HBFunctions.hb_add(this.hbHandle, ref nativeJob); + + // Second pass. Apply normal options. + nativeJob.pass = 2; + nativeJob.advanced_opts = originalX264Options; + + HBFunctions.hb_add(this.hbHandle, ref nativeJob); + } + else + { + // One pass job. + nativeJob.pass = 0; + nativeJob.advanced_opts = originalX264Options; + + HBFunctions.hb_add(this.hbHandle, ref nativeJob); + } + + HBFunctions.hb_start(this.hbHandle); + + this.encodePollTimer = new System.Timers.Timer(); + this.encodePollTimer.Interval = EncodePollIntervalMs; + + this.encodePollTimer.Elapsed += (o, e) => + { + this.PollEncodeProgress(); + }; + this.encodePollTimer.Start(); + } + + /// <summary> + /// Pauses the current encode. + /// </summary> + public void PauseEncode() + { + HBFunctions.hb_pause(this.hbHandle); + } + + /// <summary> + /// Resumes a paused encode. + /// </summary> + public void ResumeEncode() + { + HBFunctions.hb_resume(this.hbHandle); + } + + /// <summary> + /// Stops the current encode. + /// </summary> + public void StopEncode() + { + HBFunctions.hb_stop(this.hbHandle); + + // Also remove all jobs from the queue (in case we stopped a 2-pass encode) + var currentJobs = new List<IntPtr>(); + + int jobs = HBFunctions.hb_count(this.hbHandle); + for (int i = 0; i < jobs; i++) + { + currentJobs.Add(HBFunctions.hb_job(this.hbHandle, 0)); + } + + foreach (IntPtr job in currentJobs) + { + HBFunctions.hb_rem(this.hbHandle, job); + } + } + + /// <summary> + /// Gets the final size for a given encode job. + /// </summary> + /// <param name="job">The encode job to use.</param> + /// <param name="width">The storage width.</param> + /// <param name="height">The storage height.</param> + /// <param name="parWidth">The pixel aspect X number.</param> + /// <param name="parHeight">The pixel aspect Y number.</param> + public void GetSize(EncodeJob job, out int width, out int height, out int parWidth, out int parHeight) + { + if (job.EncodingProfile.Anamorphic == Anamorphic.None) + { + Title title = this.GetTitle(job.Title); + Size storageDimensions = CalculateNonAnamorphicOutput(job.EncodingProfile, title); + + width = storageDimensions.Width; + height = storageDimensions.Height; + + parWidth = 1; + parHeight = 1; + + return; + } + + var nativeJob = InteropUtilities.ReadStructure<hb_job_s>(this.GetOriginalTitle(job.Title).job); + List<IntPtr> allocatedMemory = this.ApplyJob(ref nativeJob, job); + + int refWidth = 0; + int refHeight = 0; + int refParWidth = 0; + int refParHeight = 0; + HBFunctions.hb_set_job(this.hbHandle, job.Title, ref nativeJob); + HBFunctions.hb_set_anamorphic_size_by_index(this.hbHandle, job.Title, ref refWidth, ref refHeight, ref refParWidth, ref refParHeight); + InteropUtilities.FreeMemory(allocatedMemory); + + width = refWidth; + height = refHeight; + parWidth = refParWidth; + parHeight = refParHeight; + } + + /// <summary> + /// Frees any resources associated with this object. + /// </summary> + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + /// <summary> + /// Call before app shutdown. Performs global cleanup. + /// </summary> + public static void DisposeGlobal() + { + HBFunctions.hb_global_close(); + } + + /// <summary> + /// Frees any resources associated with this object. + /// </summary> + /// <param name="disposing">True if managed objects as well as unmanaged should be disposed.</param> + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + // Free other state (managed objects). + } + + // Free unmanaged objects. + IntPtr handlePtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr))); + Marshal.WriteIntPtr(handlePtr, this.hbHandle); + HBFunctions.hb_close(handlePtr); + Marshal.FreeHGlobal(handlePtr); + } + + /// <summary> + /// Checks the status of the ongoing scan. + /// </summary> + private void PollScanProgress() + { + var state = new hb_state_s(); + HBFunctions.hb_get_state(this.hbHandle, ref state); + + if (state.state == NativeConstants.HB_STATE_SCANNING) + { + if (this.ScanProgress != null) + { + int currentTitle = state.param.scanning.title_cur; + int totalTitles = state.param.scanning.title_count; + this.ScanProgress(this, new ScanProgressEventArgs { CurrentTitle = currentTitle, Titles = totalTitles }); + } + } + else if (state.state == NativeConstants.HB_STATE_SCANDONE) + { + this.titles = new List<Title>(); + + IntPtr listPtr = HBFunctions.hb_get_titles(this.hbHandle); + this.originalTitles = InteropUtilities.ConvertList<hb_title_s>(listPtr); + + foreach (hb_title_s title in this.originalTitles) + { + var newTitle = this.ConvertTitle(title); + this.titles.Add(newTitle); + } + + if (this.originalTitles.Count > 0) + { + var nativeJob = InteropUtilities.ReadStructure<hb_job_s>(this.originalTitles[0].job); + this.featureTitle = nativeJob.feature; + } + else + { + this.featureTitle = 0; + } + + this.scanPollTimer.Stop(); + + if (this.ScanCompleted != null) + { + this.ScanCompleted(this, new EventArgs()); + } + } + } + + /// <summary> + /// Checks the status of the ongoing encode. + /// </summary> + private void PollEncodeProgress() + { + hb_state_s state = new hb_state_s(); + HBFunctions.hb_get_state(this.hbHandle, ref state); + + if (state.state == NativeConstants.HB_STATE_WORKING) + { + if (this.EncodeProgress != null) + { + int pass = 1; + int rawJobNumber = state.param.working.job_cur; + + if (this.currentJob.EncodingProfile.TwoPass) + { + if (this.subtitleScan) + { + switch (rawJobNumber) + { + case 1: + pass = -1; + break; + case 2: + pass = 1; + break; + case 3: + pass = 2; + break; + default: + break; + } + } + else + { + switch (rawJobNumber) + { + case 1: + pass = 1; + break; + case 2: + pass = 2; + break; + default: + break; + } + } + } + else + { + if (this.subtitleScan) + { + switch (rawJobNumber) + { + case 1: + pass = -1; + break; + case 2: + pass = 1; + break; + default: + break; + } + } + else + { + pass = 1; + } + } + + var progressEventArgs = new EncodeProgressEventArgs + { + FractionComplete = state.param.working.progress, + CurrentFrameRate = state.param.working.rate_cur, + AverageFrameRate = state.param.working.rate_avg, + EstimatedTimeLeft = new TimeSpan(state.param.working.hours, state.param.working.minutes, state.param.working.seconds), + Pass = pass + }; + + this.EncodeProgress(this, progressEventArgs); + } + } + else if (state.state == NativeConstants.HB_STATE_MUXING) + { + //System.Diagnostics.Debug.WriteLine("Muxing..."); + } + else if (state.state == NativeConstants.HB_STATE_WORKDONE) + { + InteropUtilities.FreeMemory(this.encodeAllocatedMemory); + this.encodePollTimer.Stop(); + + if (this.EncodeCompleted != null) + { + this.EncodeCompleted(this, new EncodeCompletedEventArgs { Error = state.param.workdone.error > 0 }); + } + } + } + + /// <summary> + /// Applies the encoding job to the native memory structure and returns a list of memory + /// locations allocated during this. + /// </summary> + /// <param name="nativeJob">The native structure to apply to job info to.</param> + /// <param name="job">The job info to apply.</param> + /// <returns>The list of memory locations allocated for the job.</returns> + private List<IntPtr> ApplyJob(ref hb_job_s nativeJob, EncodeJob job) + { + return this.ApplyJob(ref nativeJob, job, false, 0, 0, 0); + } + + /// <summary> + /// Applies the encoding job to the native memory structure and returns a list of memory + /// locations allocated during this. + /// </summary> + /// <param name="nativeJob">The native structure to apply to job info to.</param> + /// <param name="job">The job info to apply.</param> + /// <param name="preview">True if this is a preview encode.</param> + /// <param name="previewNumber">The preview number (0-based) to encode.</param> + /// <param name="previewSeconds">The number of seconds in the preview.</param> + /// <param name="overallSelectedLengthSeconds">The currently selected encode length. Used in preview + /// for calculating bitrate when the target size would be wrong.</param> + /// <returns>The list of memory locations allocated for the job.</returns> + private List<IntPtr> ApplyJob(ref hb_job_s nativeJob, EncodeJob job, bool preview, int previewNumber, int previewSeconds, double overallSelectedLengthSeconds) + { + var allocatedMemory = new List<IntPtr>(); + Title title = this.GetTitle(job.Title); + hb_title_s originalTitle = this.GetOriginalTitle(job.Title); + + EncodingProfile profile = job.EncodingProfile; + + if (preview) + { + nativeJob.start_at_preview = previewNumber + 1; + nativeJob.seek_points = this.previewCount; + + // There are 90,000 PTS per second. + nativeJob.pts_to_stop = previewSeconds * 90000; + } + else + { + switch (job.RangeType) + { + case VideoRangeType.Chapters: + + if (job.ChapterStart > 0 && job.ChapterEnd > 0) + { + nativeJob.chapter_start = job.ChapterStart; + nativeJob.chapter_end = job.ChapterEnd; + } + else + { + nativeJob.chapter_start = 1; + nativeJob.chapter_end = title.Chapters.Count; + } + + break; + case VideoRangeType.Seconds: + if (job.SecondsStart < 0 || job.SecondsEnd < 0 || job.SecondsStart >= job.SecondsEnd) + { + throw new ArgumentException("Seconds range " + job.SecondsStart + "-" + job.SecondsEnd + " is invalid.", "job"); + } + + // For some reason "pts_to_stop" actually means the number of pts to stop AFTER the start point. + nativeJob.pts_to_start = (int)(job.SecondsStart * 90000); + nativeJob.pts_to_stop = (int)((job.SecondsEnd - job.SecondsStart) * 90000); + break; + case VideoRangeType.Frames: + if (job.FramesStart < 0 || job.FramesEnd < 0 || job.FramesStart >= job.FramesEnd) + { + throw new ArgumentException("Frames range " + job.FramesStart + "-" + job.FramesEnd + " is invalid.", "job"); + } + + // "frame_to_stop" actually means the number of frames total to encode AFTER the start point. + nativeJob.frame_to_start = job.FramesStart; + nativeJob.frame_to_stop = job.FramesEnd - job.FramesStart; + break; + } + } + + nativeJob.chapter_markers = profile.IncludeChapterMarkers ? 1 : 0; + + Cropping crop; + + if (profile.CustomCropping) + { + crop = profile.Cropping; + } + else + { + crop = title.AutoCropDimensions; + } + + nativeJob.crop[0] = crop.Top; + nativeJob.crop[1] = crop.Bottom; + nativeJob.crop[2] = crop.Left; + nativeJob.crop[3] = crop.Right; + + var filterList = new List<IntPtr>(); + if (profile.Deinterlace != Deinterlace.Off) + { + nativeJob.deinterlace = 1; + string settings = null; + + switch (profile.Deinterlace) + { + case Deinterlace.Fast: + settings = "-1"; + break; + case Deinterlace.Slow: + settings = "2"; + break; + case Deinterlace.Slower: + settings = "0"; + break; + case Deinterlace.Custom: + settings = profile.CustomDeinterlace; + break; + default: + break; + } + + this.AddFilter(filterList, NativeConstants.HB_FILTER_DEINTERLACE, settings, allocatedMemory); + } + else + { + nativeJob.deinterlace = 0; + } + + if (profile.Detelecine != Detelecine.Off) + { + string settings = null; + if (profile.Detelecine == Detelecine.Custom) + { + settings = profile.CustomDetelecine; + } + + this.AddFilter(filterList, NativeConstants.HB_FILTER_DETELECINE, settings, allocatedMemory); + } + + if (profile.Decomb != Decomb.Off) + { + string settings = null; + if (profile.Decomb == Decomb.Custom) + { + settings = profile.CustomDecomb; + } + + this.AddFilter(filterList, NativeConstants.HB_FILTER_DECOMB, settings, allocatedMemory); + } + + if (profile.Deblock > 0) + { + this.AddFilter(filterList, NativeConstants.HB_FILTER_DEBLOCK, profile.Deblock.ToString(), allocatedMemory); + } + + if (profile.Denoise != Denoise.Off) + { + string settings = null; + switch (profile.Denoise) + { + case Denoise.Weak: + settings = "2:1:2:3"; + break; + case Denoise.Medium: + settings = "3:2:2:3"; + break; + case Denoise.Strong: + settings = "7:7:5:5"; + break; + case Denoise.Custom: + settings = profile.CustomDenoise; + break; + default: + break; + } + + this.AddFilter(filterList, NativeConstants.HB_FILTER_DENOISE, settings, allocatedMemory); + } + + NativeList filterListNative = InteropUtilities.CreateIntPtrList(filterList); + nativeJob.filters = filterListNative.ListPtr; + allocatedMemory.AddRange(filterListNative.AllocatedMemory); + + int width = profile.Width; + int height = profile.Height; + + int cropHorizontal = crop.Left + crop.Right; + int cropVertical = crop.Top + crop.Bottom; + + if (width == 0) + { + width = title.Resolution.Width - cropHorizontal; + } + + if (profile.MaxWidth > 0 && width > profile.MaxWidth) + { + width = profile.MaxWidth; + } + + if (height == 0) + { + height = title.Resolution.Height - cropVertical; + } + + if (profile.MaxHeight > 0 && height > profile.MaxHeight) + { + height = profile.MaxHeight; + } + + nativeJob.grayscale = profile.Grayscale ? 1 : 0; + + switch (profile.Anamorphic) + { + case Anamorphic.None: + nativeJob.anamorphic.mode = 0; + + Size outputSize = CalculateNonAnamorphicOutput(profile, title); + width = outputSize.Width; + height = outputSize.Height; + + nativeJob.anamorphic.keep_display_aspect = profile.KeepDisplayAspect ? 1 : 0; + break; + case Anamorphic.Strict: + nativeJob.anamorphic.mode = 1; + break; + case Anamorphic.Loose: + nativeJob.anamorphic.mode = 2; + break; + case Anamorphic.Custom: + nativeJob.anamorphic.mode = 3; + + nativeJob.modulus = profile.Modulus; + + if (profile.UseDisplayWidth) + { + if (profile.KeepDisplayAspect) + { + int cropWidth = title.Resolution.Width - cropHorizontal; + int cropHeight = title.Resolution.Height - cropVertical; + + double displayAspect = ((double)(cropWidth * title.ParVal.Width)) / (cropHeight * title.ParVal.Height); + int displayWidth = profile.DisplayWidth; + + if (profile.Height > 0) + { + displayWidth = (int)((double)profile.Height * displayAspect); + } + else if (displayWidth > 0) + { + height = (int)((double)displayWidth / displayAspect); + } + else + { + displayWidth = (int)((double)cropHeight * displayAspect); + } + + nativeJob.anamorphic.dar_width = displayWidth; + nativeJob.anamorphic.dar_height = height; + nativeJob.anamorphic.keep_display_aspect = 1; + } + + nativeJob.anamorphic.dar_width = profile.DisplayWidth; + nativeJob.anamorphic.dar_height = height; + nativeJob.anamorphic.keep_display_aspect = profile.KeepDisplayAspect ? 1 : 0; + } + else + { + nativeJob.anamorphic.par_width = profile.PixelAspectX; + nativeJob.anamorphic.par_height = profile.PixelAspectY; + nativeJob.anamorphic.keep_display_aspect = 0; + } + break; + default: + break; + } + + nativeJob.width = width; + nativeJob.height = height; + + nativeJob.maxWidth = profile.MaxWidth; + nativeJob.maxHeight = profile.MaxHeight; + + switch (profile.VideoEncoder) + { + case VideoEncoder.X264: + nativeJob.vcodec = NativeConstants.HB_VCODEC_X264; + break; + case VideoEncoder.Theora: + nativeJob.vcodec = NativeConstants.HB_VCODEC_THEORA; + break; + case VideoEncoder.FFMpeg: + nativeJob.vcodec = NativeConstants.HB_VCODEC_FFMPEG; + break; + default: + break; + } + + if (profile.Framerate == 0) + { + nativeJob.cfr = 0; + } + else + { + if (profile.PeakFramerate) + { + nativeJob.cfr = 2; + } + else + { + nativeJob.cfr = 1; + } + + nativeJob.vrate = 27000000; + nativeJob.vrate_base = Converters.FramerateToVrate(profile.Framerate); + } + + // vfr + // areBframes + // color_matrix + List<hb_audio_s> titleAudio = InteropUtilities.ConvertList<hb_audio_s>(originalTitle.list_audio); + + var audioList = new List<hb_audio_s>(); + int numTracks = 0; + + List<Tuple<AudioEncoding, int>> outputTrackList = this.GetOutputTracks(job, title); + + foreach (Tuple<AudioEncoding, int> outputTrack in outputTrackList) + { + audioList.Add(ConvertAudioBack(outputTrack.Item1, titleAudio[outputTrack.Item2 - 1], outputTrack.Item2, numTracks++, allocatedMemory)); + } + + NativeList nativeAudioList = InteropUtilities.ConvertListBack<hb_audio_s>(audioList); + nativeJob.list_audio = nativeAudioList.ListPtr; + allocatedMemory.AddRange(nativeAudioList.AllocatedMemory); + + // Create a new empty list + int totalSubtitles = 0; + if (job.Subtitles != null) + { + if (job.Subtitles.SourceSubtitles != null) + { + totalSubtitles += job.Subtitles.SourceSubtitles.Count; + } + + if (job.Subtitles.SrtSubtitles != null) + { + totalSubtitles += job.Subtitles.SrtSubtitles.Count; + } + } + + NativeList nativeSubtitleList = InteropUtilities.CreateNativeList(totalSubtitles + 2); + nativeJob.list_subtitle = nativeSubtitleList.ListPtr; + allocatedMemory.AddRange(nativeSubtitleList.AllocatedMemory); + + if (job.Subtitles != null) + { + if (job.Subtitles.SourceSubtitles != null && job.Subtitles.SourceSubtitles.Count > 0) + { + List<hb_subtitle_s> titleSubtitles = InteropUtilities.ConvertList<hb_subtitle_s>(originalTitle.list_subtitle); + + foreach (SourceSubtitle sourceSubtitle in job.Subtitles.SourceSubtitles) + { + if (sourceSubtitle.TrackNumber == 0) + { + // Use subtitle search. + nativeJob.select_subtitle_config.force = sourceSubtitle.Forced ? 1 : 0; + nativeJob.select_subtitle_config.default_track = sourceSubtitle.Default ? 1 : 0; + + if (!sourceSubtitle.BurnedIn) + { + nativeJob.select_subtitle_config.dest = hb_subtitle_config_s_subdest.PASSTHRUSUB; + } + + nativeJob.indepth_scan = 1; + } + else + { + // Use specified subtitle. + hb_subtitle_s nativeSubtitle = titleSubtitles[sourceSubtitle.TrackNumber - 1]; + var subtitleConfig = new hb_subtitle_config_s(); + + subtitleConfig.force = sourceSubtitle.Forced ? 1 : 0; + subtitleConfig.default_track = sourceSubtitle.Default ? 1 : 0; + + bool supportsBurn = nativeSubtitle.source == hb_subtitle_s_subsource.VOBSUB || nativeSubtitle.source == hb_subtitle_s_subsource.SSASUB; + if (supportsBurn && sourceSubtitle.BurnedIn) + { + subtitleConfig.dest = hb_subtitle_config_s_subdest.RENDERSUB; + } + else + { + subtitleConfig.dest = hb_subtitle_config_s_subdest.PASSTHRUSUB; + } + + int subtitleAddSucceded = HBFunctions.hb_subtitle_add(ref nativeJob, ref subtitleConfig, sourceSubtitle.TrackNumber - 1); + if (subtitleAddSucceded == 0) + { + System.Diagnostics.Debug.WriteLine("Subtitle add failed"); + } + } + } + } + + if (job.Subtitles.SrtSubtitles != null) + { + foreach (SrtSubtitle srtSubtitle in job.Subtitles.SrtSubtitles) + { + var subtitleConfig = new hb_subtitle_config_s(); + + subtitleConfig.src_codeset = srtSubtitle.CharacterCode; + subtitleConfig.src_filename = srtSubtitle.FileName; + subtitleConfig.offset = srtSubtitle.Offset; + //subtitleConfig.dest = hb_subtitle_config_s_subdest.PASSTHRUSUB; + subtitleConfig.default_track = srtSubtitle.Default ? 1 : 0; + + int srtAddSucceded = HBFunctions.hb_srt_add(ref nativeJob, ref subtitleConfig, srtSubtitle.LanguageCode); + if (srtAddSucceded == 0) + { + System.Diagnostics.Debug.WriteLine("SRT add failed"); + } + } + } + } + + if (profile.OutputFormat == OutputFormat.Mp4) + { + nativeJob.mux = NativeConstants.HB_MUX_MP4; + } + else + { + nativeJob.mux = NativeConstants.HB_MUX_MKV; + } + + nativeJob.file = job.OutputPath; + + nativeJob.largeFileSize = profile.LargeFile ? 1 : 0; + nativeJob.mp4_optimize = profile.Optimize ? 1 : 0; + nativeJob.ipod_atom = profile.IPod5GSupport ? 1 : 0; + + if (title.AngleCount > 1) + { + nativeJob.angle = job.Angle; + } + + switch (profile.VideoEncodeRateType) + { + case VideoEncodeRateType.ConstantQuality: + nativeJob.vquality = (float)profile.Quality; + nativeJob.vbitrate = 0; + break; + case VideoEncodeRateType.AverageBitrate: + nativeJob.vquality = -1; + nativeJob.vbitrate = profile.VideoBitrate; + break; + case VideoEncodeRateType.TargetSize: + nativeJob.vquality = -1; + nativeJob.vbitrate = this.CalculateBitrate(job, profile.TargetSize, overallSelectedLengthSeconds); + break; + default: + break; + } + + // frames_to_skip + + return allocatedMemory; + } + + /// <summary> + /// Gets a list of encodings and target track indices (1-based). + /// </summary> + /// <param name="job">The encode job</param> + /// <param name="title">The title the job is meant to encode.</param> + /// <returns>A list of encodings and target track indices (1-based).</returns> + private List<Tuple<AudioEncoding, int>> GetOutputTracks(EncodeJob job, Title title) + { + var list = new List<Tuple<AudioEncoding, int>>(); + + foreach (AudioEncoding encoding in job.EncodingProfile.AudioEncodings) + { + if (encoding.InputNumber == 0) + { + // Add this encoding for all chosen tracks + foreach (int chosenTrack in job.ChosenAudioTracks) + { + list.Add(new Tuple<AudioEncoding, int>(encoding, chosenTrack)); + } + } + else if (encoding.InputNumber <= job.ChosenAudioTracks.Count) + { + // Add this encoding for the specified track, if it exists + int trackNumber = job.ChosenAudioTracks[encoding.InputNumber - 1]; + + // In normal cases we'll never have a chosen audio track that doesn't exist but when batch encoding + // we just choose the first audio track without checking if it exists. + if (trackNumber <= title.AudioTracks.Count) + { + list.Add(new Tuple<AudioEncoding, int>(encoding, trackNumber)); + } + } + } + + return list; + } + + /// <summary> + /// Adds a filter to the given filter list. + /// </summary> + /// <param name="filterList">The filter list to add to.</param> + /// <param name="filterType">The type of filter.</param> + /// <param name="settings">Settings for the filter.</param> + /// <param name="allocatedMemory">The list of allocated memory.</param> + private void AddFilter(List<IntPtr> filterList, int filterType, string settings, List<IntPtr> allocatedMemory) + { + IntPtr settingsNativeString = Marshal.StringToHGlobalAnsi(settings); + filterList.Add(HBFunctions.hb_get_filter_object(filterType, settingsNativeString)); + + allocatedMemory.Add(settingsNativeString); + } + + /// <summary> + /// Gets the title, given the 1-based index. + /// </summary> + /// <param name="titleIndex">The index of the title (1-based).</param> + /// <returns>The requested Title.</returns> + private Title GetTitle(int titleIndex) + { + return this.Titles.SingleOrDefault(title => title.TitleNumber == titleIndex); + } + + /// <summary> + /// Gets the native title object from the title index. + /// </summary> + /// <param name="titleIndex">The index of the title (1-based).</param> + /// <returns>Gets the native title object for the given index.</returns> + private hb_title_s GetOriginalTitle(int titleIndex) + { + List<hb_title_s> matchingTitles = this.originalTitles.Where(title => title.index == titleIndex).ToList(); + if (matchingTitles.Count == 0) + { + throw new ArgumentException("Could not find specified title."); + } + + if (matchingTitles.Count > 1) + { + throw new ArgumentException("Multiple titles matched."); + } + + return matchingTitles[0]; + } + + /// <summary> + /// Applies an audio encoding to a native audio encoding base structure. + /// </summary> + /// <param name="encoding">The encoding to apply.</param> + /// <param name="baseStruct">The base native structure.</param> + /// <param name="track"></param> + /// <param name="outputTrack"></param> + /// <param name="allocatedMemory">The collection of allocated memory.</param> + /// <returns>The resulting native audio structure.</returns> + private hb_audio_s ConvertAudioBack(AudioEncoding encoding, hb_audio_s baseStruct, int track, int outputTrack, List<IntPtr> allocatedMemory) + { + hb_audio_s nativeAudio = baseStruct; + + //nativeAudio.config.input.track = track; + nativeAudio.config.output.track = outputTrack; + + if (encoding.Encoder == AudioEncoder.Passthrough) + { + // If we've been given a general "Passthrough" codec, see if it's valid for this input track. + if ((baseStruct.config.input.codec & NativeConstants.HB_ACODEC_PASS_MASK) > 0) + { + // We can do passthrough for this input. + nativeAudio.config.output.codec = nativeAudio.config.input.codec | NativeConstants.HB_ACODEC_PASS_FLAG; + } + else + { + // We can't do passthrough for this input. Set it to a DTS passthrough, which will cause the track to be dropped. + nativeAudio.config.output.codec = NativeConstants.HB_ACODEC_DCA_PASS; + } + } + else + { + nativeAudio.config.output.codec = Converters.AudioEncoderToNative(encoding.Encoder); + } + + if (encoding.Encoder != AudioEncoder.Passthrough && encoding.Encoder != AudioEncoder.Ac3Passthrough && encoding.Encoder != AudioEncoder.DtsPassthrough) + { + nativeAudio.config.output.bitrate = encoding.Bitrate; + nativeAudio.config.output.dynamic_range_compression = 0.0; + nativeAudio.config.output.gain = encoding.Gain; + + if (encoding.Mixdown == Mixdown.Auto) + { + nativeAudio.config.output.mixdown = HBFunctions.hb_get_default_mixdown(nativeAudio.config.output.codec, nativeAudio.config.input.channel_layout); + } + else + { + nativeAudio.config.output.mixdown = Converters.MixdownToNative(encoding.Mixdown); + } + + if (encoding.SampleRateRaw == 0) + { + nativeAudio.config.output.samplerate = nativeAudio.config.input.samplerate; + } + else + { + nativeAudio.config.output.samplerate = encoding.SampleRateRaw; + } + } + + if (!string.IsNullOrEmpty(encoding.Name)) + { + IntPtr encodingNamePtr = Marshal.StringToHGlobalAnsi(encoding.Name); + nativeAudio.config.output.name = encodingNamePtr; + allocatedMemory.Add(encodingNamePtr); + } + + nativeAudio.padding = new byte[MarshalingConstants.AudioPaddingBytes]; + + return nativeAudio; + } + + /// <summary> + /// Converts a native title to a Title object. + /// </summary> + /// <param name="title">The native title structure.</param> + /// <returns>The managed Title object.</returns> + private Title ConvertTitle(hb_title_s title) + { + var newTitle = new Title + { + TitleNumber = title.index, + Resolution = new Size(title.width, title.height), + ParVal = new Size(title.pixel_aspect_width, title.pixel_aspect_height), + Duration = TimeSpan.FromSeconds(title.duration / 90000), + AutoCropDimensions = new Cropping + { + Top = title.crop[0], + Bottom = title.crop[1], + Left = title.crop[2], + Right = title.crop[3] + }, + AspectRatio = title.aspect, + AngleCount = title.angle_count, + VideoCodecName = title.video_codec_name, + Framerate = ((double)title.rate) / title.rate_base + }; + + switch (title.type) + { + case hb_title_type_anon.HB_STREAM_TYPE: + newTitle.InputType = InputType.Stream; + break; + case hb_title_type_anon.HB_DVD_TYPE: + newTitle.InputType = InputType.Dvd; + break; + case hb_title_type_anon.HB_BD_TYPE: + newTitle.InputType = InputType.Bluray; + break; + } + + int currentSubtitleTrack = 1; + List<hb_subtitle_s> subtitleList = InteropUtilities.ConvertList<hb_subtitle_s>(title.list_subtitle); + foreach (hb_subtitle_s subtitle in subtitleList) + { + var newSubtitle = new Subtitle + { + TrackNumber = currentSubtitleTrack, + Language = subtitle.lang, + LanguageCode = subtitle.iso639_2 + }; + + if (subtitle.format == hb_subtitle_s_subtype.PICTURESUB) + { + newSubtitle.SubtitleType = SubtitleType.Picture; + } + else if (subtitle.format == hb_subtitle_s_subtype.TEXTSUB) + { + newSubtitle.SubtitleType = SubtitleType.Text; + } + + switch (subtitle.source) + { + case hb_subtitle_s_subsource.CC608SUB: + newSubtitle.SubtitleSource = SubtitleSource.CC608; + break; + case hb_subtitle_s_subsource.CC708SUB: + newSubtitle.SubtitleSource = SubtitleSource.CC708; + break; + case hb_subtitle_s_subsource.SRTSUB: + newSubtitle.SubtitleSource = SubtitleSource.SRT; + break; + case hb_subtitle_s_subsource.SSASUB: + newSubtitle.SubtitleSource = SubtitleSource.SSA; + break; + case hb_subtitle_s_subsource.TX3GSUB: + newSubtitle.SubtitleSource = SubtitleSource.TX3G; + break; + case hb_subtitle_s_subsource.UTF8SUB: + newSubtitle.SubtitleSource = SubtitleSource.UTF8; + break; + case hb_subtitle_s_subsource.VOBSUB: + newSubtitle.SubtitleSource = SubtitleSource.VobSub; + break; + default: + break; + } + + newTitle.Subtitles.Add(newSubtitle); + + currentSubtitleTrack++; + } + + int currentAudioTrack = 1; + List<hb_audio_s> audioList = InteropUtilities.ConvertList<hb_audio_s>(title.list_audio); + foreach (hb_audio_s audio in audioList) + { + var newAudio = new AudioTrack + { + TrackNumber = currentAudioTrack, + Codec = Converters.NativeToAudioCodec(audio.config.input.codec), + Language = audio.config.lang.simple, + LanguageCode = audio.config.lang.iso639_2, + Description = audio.config.lang.description, + ChannelLayout = audio.config.input.channel_layout, + SampleRate = audio.config.input.samplerate, + Bitrate = audio.config.input.bitrate + }; + + newTitle.AudioTracks.Add(newAudio); + + currentAudioTrack++; + } + + List<hb_chapter_s> chapterList = InteropUtilities.ConvertList<hb_chapter_s>(title.list_chapter); + foreach (hb_chapter_s chapter in chapterList) + { + var newChapter = new Chapter + { + ChapterNumber = chapter.index, + Duration = TimeSpan.FromSeconds(((double)chapter.duration) / 90000) + }; + + newTitle.Chapters.Add(newChapter); + } + + return newTitle; + } + + /// <summary> + /// Calculates the output size for a non-anamorphic job. + /// </summary> + /// <param name="profile">The encoding profile for the job.</param> + /// <param name="title">The title being encoded.</param> + /// <returns>The dimensions of the final encode.</returns> + private static Size CalculateNonAnamorphicOutput(EncodingProfile profile, Title title) + { + int sourceWidth = title.Resolution.Width; + int sourceHeight = title.Resolution.Height; + + int width = profile.Width; + int height = profile.Height; + + Cropping crop; + if (profile.CustomCropping) + { + crop = profile.Cropping; + } + else + { + crop = title.AutoCropDimensions; + } + + sourceWidth -= crop.Left; + sourceWidth -= crop.Right; + + sourceHeight -= crop.Top; + sourceHeight -= crop.Bottom; + + double croppedAspectRatio = ((double)sourceWidth * title.ParVal.Width) / (sourceHeight * title.ParVal.Height); + + if (width == 0) + { + width = sourceWidth; + } + + if (profile.MaxWidth > 0 && width > profile.MaxWidth) + { + width = profile.MaxWidth; + } + + if (height == 0) + { + height = sourceHeight; + } + + if (profile.MaxHeight > 0 && height > profile.MaxHeight) + { + height = profile.MaxHeight; + } + + if (profile.KeepDisplayAspect) + { + if (profile.Width == 0 && profile.Height == 0 || profile.Width == 0) + { + width = (int)((double)height * croppedAspectRatio); + if (profile.MaxWidth > 0 && width > profile.MaxWidth) + { + width = profile.MaxWidth; + height = (int)((double)width / croppedAspectRatio); + height = GetNearestValue(height, PictureAutoSizeModulus); + } + + width = GetNearestValue(width, PictureAutoSizeModulus); + } + else if (profile.Height == 0) + { + height = (int)((double)width / croppedAspectRatio); + if (profile.MaxHeight > 0 && height > profile.MaxHeight) + { + height = profile.MaxHeight; + width = (int)((double)height * croppedAspectRatio); + width = GetNearestValue(width, PictureAutoSizeModulus); + } + + height = GetNearestValue(height, PictureAutoSizeModulus); + } + } + + return new Size(width, height); + } + + /// <summary> + /// Gets the closest value to the given number divisible by the given modulus. + /// </summary> + /// <param name="number">The number to approximate.</param> + /// <param name="modulus">The modulus.</param> + /// <returns>The closest value to the given number divisible by the given modulus.</returns> + private static int GetNearestValue(int number, int modulus) + { + return modulus * ((number + modulus / 2) / modulus); + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInterop.csproj b/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInterop.csproj new file mode 100644 index 000000000..24668cadd --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInterop.csproj @@ -0,0 +1,206 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.30729</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>HandBrake.Interop</RootNamespace> + <AssemblyName>HandBrakeInterop</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <FileUpgradeFlags> + </FileUpgradeFlags> + <UpgradeBackupLocation> + </UpgradeBackupLocation> + <OldToolsVersion>3.5</OldToolsVersion> + <TargetFrameworkProfile>Client</TargetFrameworkProfile> + <PublishUrl>publish\</PublishUrl> + <Install>true</Install> + <InstallFrom>Disk</InstallFrom> + <UpdateEnabled>false</UpdateEnabled> + <UpdateMode>Foreground</UpdateMode> + <UpdateInterval>7</UpdateInterval> + <UpdateIntervalUnits>Days</UpdateIntervalUnits> + <UpdatePeriodically>false</UpdatePeriodically> + <UpdateRequired>false</UpdateRequired> + <MapFileExtensions>true</MapFileExtensions> + <ApplicationRevision>0</ApplicationRevision> + <ApplicationVersion>1.0.0.%2a</ApplicationVersion> + <IsWebBootstrapper>false</IsWebBootstrapper> + <UseApplicationTrust>false</UseApplicationTrust> + <BootstrapperEnabled>true</BootstrapperEnabled> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\x64\Debug\</OutputPath> + <DefineConstants>TRACE;DEBUG;X64</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>x64</PlatformTarget> + <CodeAnalysisLogFile>bin\Debug\HandBrakeInterop.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile> + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories> + <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets> + <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> + <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules> + <CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <OutputPath>bin\x64\Release\</OutputPath> + <DefineConstants>TRACE;X64</DefineConstants> + <Optimize>true</Optimize> + <DebugType>pdbonly</DebugType> + <PlatformTarget>x64</PlatformTarget> + <CodeAnalysisLogFile>bin\Release\HandBrakeInterop.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile> + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories> + <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets> + <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> + <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\x86\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>x86</PlatformTarget> + <CodeAnalysisLogFile>bin\Debug\HandBrakeInterop.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile> + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories> + <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets> + <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> + <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> + <OutputPath>bin\x86\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <Optimize>true</Optimize> + <DebugType>pdbonly</DebugType> + <PlatformTarget>x86</PlatformTarget> + <CodeAnalysisLogFile>bin\Release\HandBrakeInterop.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile> + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories> + <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets> + <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> + <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules> + <CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules> + </PropertyGroup> + <ItemGroup> + <Reference Include="PresentationCore"> + <RequiredTargetFramework>3.0</RequiredTargetFramework> + </Reference> + <Reference Include="System" /> + <Reference Include="System.ComponentModel.DataAnnotations" /> + <Reference Include="System.Core"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Drawing" /> + <Reference Include="System.Xaml" /> + <Reference Include="System.Xml.Linq"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data.DataSetExtensions"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + <Reference Include="WindowsBase"> + <RequiredTargetFramework>3.0</RequiredTargetFramework> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="Converters.cs" /> + <Compile Include="EncodeCompletedEventArgs.cs" /> + <Compile Include="EncodeProgressEventArgs.cs" /> + <Compile Include="HandBrakeUtils.cs" /> + <Compile Include="HandBrakeInstance.cs" /> + <Compile Include="HbLib\HBFunctions.cs" /> + <Compile Include="HbLib\hb_audio.cs" /> + <Compile Include="HbLib\hb_chapter_s.cs" /> + <Compile Include="HbLib\hb_handle_s.cs" /> + <Compile Include="HbLib\hb_subtitle.cs" /> + <Compile Include="HbLib\Misc.cs" /> + <Compile Include="HbLib\hb_job_s.cs" /> + <Compile Include="HbLib\hb_title_s.cs" /> + <Compile Include="HbLib\NativeConstants.cs" /> + <Compile Include="InteropUtilities.cs" /> + <Compile Include="Language.cs" /> + <Compile Include="LanguageCodes.cs" /> + <Compile Include="MarshalingConstants.cs" /> + <Compile Include="MessageLoggedEventArgs.cs" /> + <Compile Include="Model\Cropping.cs" /> + <Compile Include="Model\EncodeJob.cs" /> + <Compile Include="Model\Encoding\Anamorphic.cs" /> + <Compile Include="Model\Encoding\AudioEncoder.cs" /> + <Compile Include="Model\Encoding\AudioEncoding.cs" /> + <Compile Include="Model\Encoding\Decomb.cs" /> + <Compile Include="Model\Encoding\Deinterlace.cs" /> + <Compile Include="Model\Encoding\Denoise.cs" /> + <Compile Include="Model\Encoding\Detelecine.cs" /> + <Compile Include="Model\Encoding\EncodingProfile.cs" /> + <Compile Include="Model\Encoding\Mixdown.cs" /> + <Compile Include="Model\Encoding\OutputExtension.cs" /> + <Compile Include="Model\Encoding\OutputFormat.cs" /> + <Compile Include="Model\Encoding\VideoEncoder.cs" /> + <Compile Include="Model\Encoding\VideoEncodeRateType.cs" /> + <Compile Include="Model\Limits.cs" /> + <Compile Include="Model\Size.cs" /> + <Compile Include="Model\SourceSubtitle.cs" /> + <Compile Include="Model\SourceType.cs" /> + <Compile Include="Model\SrtSubtitle.cs" /> + <Compile Include="Model\Subtitles.cs" /> + <Compile Include="Model\VideoRangeType.cs" /> + <Compile Include="NativeList.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="ScanProgressEventArgs.cs" /> + <Compile Include="SourceData\AudioCodec.cs" /> + <Compile Include="SourceData\AudioTrack.cs" /> + <Compile Include="SourceData\Chapter.cs" /> + <Compile Include="SourceData\InputType.cs" /> + <Compile Include="SourceData\Subtitle.cs" /> + <Compile Include="SourceData\SubtitleSource.cs" /> + <Compile Include="SourceData\SubtitleType.cs" /> + <Compile Include="SourceData\Title.cs" /> + <Compile Include="Utilities.cs" /> + </ItemGroup> + <ItemGroup> + <BootstrapperPackage Include="Microsoft.Net.Client.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1"> + <Visible>False</Visible> + <ProductName>Windows Installer 3.1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target>--> + <Target Name="AfterBuild"> + <Copy SourceFiles="..\..\Lib\$(Platform)\hb.dll" DestinationFolder="$(OutDir)" /> + </Target> +</Project> \ No newline at end of file diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeUtils.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeUtils.cs new file mode 100644 index 000000000..89134b4ab --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeUtils.cs @@ -0,0 +1,254 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using HandBrake.SourceData; + +namespace HandBrake.Interop +{ + public static class HandBrakeUtils + { + /// <summary> + /// Estimated overhead in bytes for each frame in output container. + /// </summary> + internal const int ContainerOverheadPerFrame = 6; + + /// <summary> + /// The callback for log messages from HandBrake. + /// </summary> + private static LoggingCallback loggingCallback; + + /// <summary> + /// The callback for error messages from HandBrake. + /// </summary> + private static LoggingCallback errorCallback; + + /// <summary> + /// Fires when HandBrake has logged a message. + /// </summary> + public static event EventHandler<MessageLoggedEventArgs> MessageLogged; + + /// <summary> + /// Fires when HandBrake has logged an error. + /// </summary> + public static event EventHandler<MessageLoggedEventArgs> ErrorLogged; + + public static void RegisterLogger() + { + // Register the logger if we have not already + if (loggingCallback == null) + { + // Keep the callback as a member to prevent it from being garbage collected. + loggingCallback = new LoggingCallback(LoggingHandler); + errorCallback = new LoggingCallback(ErrorHandler); + HBFunctions.hb_register_logger(loggingCallback); + HBFunctions.hb_register_error_handler(errorCallback); + } + } + + /// <summary> + /// Handles log messages from HandBrake. + /// </summary> + /// <param name="message">The log message (including newline).</param> + public static void LoggingHandler(string message) + { + if (!string.IsNullOrEmpty(message)) + { + string[] messageParts = message.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); + + if (messageParts.Length > 0) + { + if (MessageLogged != null) + { + MessageLogged(null, new MessageLoggedEventArgs { Message = messageParts[0] }); + } + + System.Diagnostics.Debug.WriteLine(messageParts[0]); + } + } + } + + /// <summary> + /// Handles errors from HandBrake. + /// </summary> + /// <param name="message">The error message.</param> + public static void ErrorHandler(string message) + { + if (!string.IsNullOrEmpty(message)) + { + // This error happens in normal operations. Log it as a message. + if (message == "dvd: ifoOpen failed") + { + if (MessageLogged != null) + { + MessageLogged(null, new MessageLoggedEventArgs { Message = message }); + } + + return; + } + + if (ErrorLogged != null) + { + ErrorLogged(null, new MessageLoggedEventArgs { Message = message }); + } + + System.Diagnostics.Debug.WriteLine("ERROR: " + message); + } + } + + /// <summary> + /// Gets the default mixdown for the given audio encoder and channel layout. + /// </summary> + /// <param name="encoder">The output codec to be used.</param> + /// <param name="layout">The input channel layout.</param> + /// <returns>The default mixdown for the given codec and channel layout.</returns> + public static Mixdown GetDefaultMixdown(AudioEncoder encoder, int layout) + { + int defaultMixdown = HBFunctions.hb_get_default_mixdown(Converters.AudioEncoderToNative(encoder), layout); + return Converters.NativeToMixdown(defaultMixdown); + } + + /// <summary> + /// Gets the bitrate limits for the given audio codec, sample rate and mixdown. + /// </summary> + /// <param name="encoder">The audio encoder used.</param> + /// <param name="sampleRate">The sample rate used (Hz).</param> + /// <param name="mixdown">The mixdown used.</param> + /// <returns>Limits on the audio bitrate for the given settings.</returns> + public static Limits GetBitrateLimits(AudioEncoder encoder, int sampleRate, Mixdown mixdown) + { + if (mixdown == Mixdown.Auto) + { + throw new ArgumentException("Mixdown cannot be Auto."); + } + + int low = 0; + int high = 0; + + HBFunctions.hb_get_audio_bitrate_limits(Converters.AudioEncoderToNative(encoder), sampleRate, Converters.MixdownToNative(mixdown), ref low, ref high); + + return new Limits { Low = low, High = high }; + } + + /// <summary> + /// Sanitizes a mixdown given the output codec and input channel layout. + /// </summary> + /// <param name="mixdown">The desired mixdown.</param> + /// <param name="encoder">The output encoder to be used.</param> + /// <param name="layout">The input channel layout.</param> + /// <returns>A sanitized mixdown value.</returns> + public static Mixdown SanitizeMixdown(Mixdown mixdown, AudioEncoder encoder, int layout) + { + int sanitizedMixdown = HBFunctions.hb_get_best_mixdown(Converters.AudioEncoderToNative(encoder), layout, Converters.MixdownToNative(mixdown)); + return Converters.NativeToMixdown(sanitizedMixdown); + } + + /// <summary> + /// Sanitizes an audio bitrate given the output codec, sample rate and mixdown. + /// </summary> + /// <param name="audioBitrate">The desired audio bitrate.</param> + /// <param name="encoder">The output encoder to be used.</param> + /// <param name="sampleRate">The output sample rate to be used.</param> + /// <param name="mixdown">The mixdown to be used.</param> + /// <returns>A sanitized audio bitrate.</returns> + public static int SanitizeAudioBitrate(int audioBitrate, AudioEncoder encoder, int sampleRate, Mixdown mixdown) + { + return HBFunctions.hb_get_best_audio_bitrate(Converters.AudioEncoderToNative(encoder), audioBitrate, sampleRate, Converters.MixdownToNative(mixdown)); + } + + /// <summary> + /// Gets the total number of seconds on the given encode job. + /// </summary> + /// <param name="job">The encode job to query.</param> + /// <param name="title">The title being encoded.</param> + /// <returns>The total number of seconds of video to encode.</returns> + internal static double GetJobLengthSeconds(EncodeJob job, Title title) + { + switch (job.RangeType) + { + case VideoRangeType.Chapters: + TimeSpan duration = TimeSpan.Zero; + for (int i = job.ChapterStart; i <= job.ChapterEnd; i++) + { + duration += title.Chapters[i - 1].Duration; + } + + return duration.TotalSeconds; + case VideoRangeType.Seconds: + return job.SecondsEnd - job.SecondsStart; + case VideoRangeType.Frames: + return (job.FramesEnd - job.FramesStart) / title.Framerate; + } + + return 0; + } + + /// <summary> + /// Gets the number of audio samples used per frame for the given audio encoder. + /// </summary> + /// <param name="encoder">The encoder to query.</param> + /// <returns>The number of audio samples used per frame for the given + /// audio encoder.</returns> + internal static int GetAudioSamplesPerFrame(AudioEncoder encoder) + { + switch (encoder) + { + case AudioEncoder.Faac: + case AudioEncoder.Vorbis: + return 1024; + case AudioEncoder.Lame: + return 1152; + case AudioEncoder.Ac3: + case AudioEncoder.Passthrough: + case AudioEncoder.Ac3Passthrough: + case AudioEncoder.DtsPassthrough: + return 1536; + } + + System.Diagnostics.Debug.Assert(true, "Audio encoder unrecognized."); + return 0; + } + + /// <summary> + /// Gets the size in bytes for the audio with the given parameters. + /// </summary> + /// <param name="job">The encode job.</param> + /// <param name="lengthSeconds">The length of the encode in seconds.</param> + /// <param name="title">The title to encode.</param> + /// <param name="outputTrackList">The list of tracks to encode.</param> + /// <returns>The size in bytes for the audio with the given parameters.</returns> + internal static long GetAudioSize(EncodeJob job, double lengthSeconds, Title title, List<Tuple<AudioEncoding, int>> outputTrackList) + { + long audioBytes = 0; + + foreach (Tuple<AudioEncoding, int> outputTrack in outputTrackList) + { + AudioEncoding encoding = outputTrack.Item1; + AudioTrack track = title.AudioTracks[outputTrack.Item2 - 1]; + + int samplesPerFrame = HandBrakeUtils.GetAudioSamplesPerFrame(encoding.Encoder); + int audioBitrate; + + if (encoding.Encoder == AudioEncoder.Passthrough || + encoding.Encoder == AudioEncoder.Ac3Passthrough || + encoding.Encoder == AudioEncoder.DtsPassthrough) + { + // Input bitrate is in bits/second. + audioBitrate = track.Bitrate / 8; + } + else + { + // Output bitrate is in kbps. + audioBitrate = encoding.Bitrate * 1000 / 8; + } + + audioBytes += (long)(lengthSeconds * audioBitrate); + + // Audio overhead + audioBytes += encoding.SampleRateRaw * ContainerOverheadPerFrame / samplesPerFrame; + } + + return audioBytes; + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/HbFunctions.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/HbFunctions.cs new file mode 100644 index 000000000..fa5a321ca --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/HbFunctions.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace HandBrake.Interop +{ + public static class HBFunctions + { + [DllImport("hb.dll", EntryPoint = "hb_register_logger", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_register_logger(LoggingCallback callback); + + [DllImport("hb.dll", EntryPoint = "hb_register_error_handler", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_register_error_handler(LoggingCallback callback); + + /// Return Type: hb_handle_t* + ///verbose: int + ///update_check: int + [DllImport("hb.dll", EntryPoint = "hb_init", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr hb_init(int verbose, int update_check); + + + /// Return Type: hb_handle_t* + ///verbose: int + ///update_check: int + [DllImport("hb.dll", EntryPoint = "hb_init_dl", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr hb_init_dl(int verbose, int update_check); + + + /// Return Type: char* + ///param0: hb_handle_t* + [DllImport("hb.dll", EntryPoint = "hb_get_version", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr hb_get_version(ref hb_handle_s param0); + + + /// Return Type: int + ///param0: hb_handle_t* + [DllImport("hb.dll", EntryPoint = "hb_get_build", CallingConvention = CallingConvention.Cdecl)] + public static extern int hb_get_build(ref hb_handle_s param0); + + + /// Return Type: int + ///h: hb_handle_t* + ///version: char** + [DllImport("hb.dll", EntryPoint = "hb_check_update", CallingConvention = CallingConvention.Cdecl)] + public static extern int hb_check_update(ref hb_handle_s h, ref IntPtr version); + + + /// Return Type: void + ///param0: hb_handle_t* + ///param1: int + [DllImport("hb.dll", EntryPoint = "hb_set_cpu_count", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_set_cpu_count(ref hb_handle_s param0, int param1); + + + /// Return Type: char* + ///path: char* + [DllImport("hb.dll", EntryPoint = "hb_dvd_name", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr hb_dvd_name(IntPtr path); + + + /// Return Type: void + ///enable: int + [DllImport("hb.dll", EntryPoint = "hb_dvd_set_dvdnav", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_dvd_set_dvdnav(int enable); + + + /// Return Type: void + ///param0: hb_handle_t* + ///path: char* + ///title_index: int + ///preview_count: int + ///store_previews: int + [DllImport("hb.dll", EntryPoint = "hb_scan", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_scan(IntPtr hbHandle, [In] [MarshalAs(UnmanagedType.LPStr)] string path, int title_index, int preview_count, int store_previews, ulong min_duration); + + [DllImport("hb.dll", EntryPoint = "hb_scan_stop", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_scan_stop(IntPtr hbHandle); + + /// Return Type: hb_list_t* + ///param0: hb_handle_t* + [DllImport("hb.dll", EntryPoint = "hb_get_titles", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr hb_get_titles(IntPtr hbHandle); + + + /// Return Type: int + ///buf: hb_buffer_t* + ///width: int + ///height: int + ///color_equal: int + ///color_diff: int + ///threshold: int + ///prog_equal: int + ///prog_diff: int + ///prog_threshold: int + [DllImport("hb.dll", EntryPoint = "hb_detect_comb", CallingConvention = CallingConvention.Cdecl)] + public static extern int hb_detect_comb(ref hb_buffer_s buf, int width, int height, int color_equal, int color_diff, int threshold, int prog_equal, int prog_diff, int prog_threshold); + + [DllImport("hb.dll", EntryPoint = "hb_get_preview_by_index", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_get_preview_by_index(IntPtr hbHandle, int title_index, int picture, IntPtr buffer); + + /// Return Type: void + ///param0: hb_handle_t* + ///param1: hb_title_t* + ///param2: int + ///param3: uint8_t* + [DllImport("hb.dll", EntryPoint = "hb_get_preview", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_get_preview(IntPtr hbHandle, ref hb_title_s title, int preview, IntPtr buffer); + + + /// Return Type: void + ///param0: hb_job_t* + ///ratio: double + ///pixels: int + [DllImport("hb.dll", EntryPoint = "hb_set_size", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_set_size(ref hb_job_s param0, double ratio, int pixels); + + [DllImport("hb.dll", EntryPoint = "hb_set_anamorphic_size_by_index", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_set_anamorphic_size_by_index(IntPtr hbHandle, int title_index, ref int output_width, ref int output_height, ref int output_par_width, ref int output_par_height); + + /// Return Type: void + ///param0: hb_job_t* + ///output_width: int* + ///output_height: int* + ///output_par_width: int* + ///output_par_height: int* + [DllImport("hb.dll", EntryPoint = "hb_set_anamorphic_size", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_set_anamorphic_size(ref hb_job_s job, ref int output_width, ref int output_height, ref int output_par_width, ref int output_par_height); + + + /// Return Type: int + ///param0: hb_handle_t* + [DllImport("hb.dll", EntryPoint = "hb_count", CallingConvention = CallingConvention.Cdecl)] + public static extern int hb_count(IntPtr hbHandle); + + + /// Return Type: hb_job_t* + ///param0: hb_handle_t* + ///param1: int + [DllImport("hb.dll", EntryPoint = "hb_job", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr hb_job(IntPtr hbHandle, int jobIndex); + + [DllImport("hb.dll", EntryPoint = "hb_set_chapter_name", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_set_chapter_name(IntPtr hbHandle, int title_index, int chapter_index, [In] [MarshalAs(UnmanagedType.LPStr)] string chapter_name); + + [DllImport("hb.dll", EntryPoint = "hb_set_job", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_set_job(IntPtr hbHandle, int title_index, ref hb_job_s job); + + /// Return Type: void + ///param0: hb_handle_t* + ///param1: hb_job_t* + [DllImport("hb.dll", EntryPoint = "hb_add", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_add(IntPtr hbHandle, ref hb_job_s job); + + + /// Return Type: void + ///param0: hb_handle_t* + ///param1: hb_job_t* + [DllImport("hb.dll", EntryPoint = "hb_rem", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_rem(IntPtr hbHandle, IntPtr job); + + + /// Return Type: void + ///param0: hb_handle_t* + [DllImport("hb.dll", EntryPoint = "hb_start", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_start(IntPtr hbHandle); + + + /// Return Type: void + ///param0: hb_handle_t* + [DllImport("hb.dll", EntryPoint = "hb_pause", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_pause(IntPtr hbHandle); + + + /// Return Type: void + ///param0: hb_handle_t* + [DllImport("hb.dll", EntryPoint = "hb_resume", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_resume(IntPtr hbHandle); + + + /// Return Type: void + ///param0: hb_handle_t* + [DllImport("hb.dll", EntryPoint = "hb_stop", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_stop(IntPtr hbHandle); + + [DllImport("hb.dll", EntryPoint = "hb_get_filter_object", CallingConvention = CallingConvention.Cdecl)] + //public static extern IntPtr hb_get_filter_object(int filter_id, [In] [MarshalAs(UnmanagedType.LPStr)] string settings); + public static extern IntPtr hb_get_filter_object(int filter_id, IntPtr settings); + + /// Return Type: void + ///param0: hb_handle_t* + ///param1: hb_state_t* + [DllImport("hb.dll", EntryPoint = "hb_get_state", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_get_state(IntPtr hbHandle, ref hb_state_s state); + + + /// Return Type: void + ///param0: hb_handle_t* + ///param1: hb_state_t* + [DllImport("hb.dll", EntryPoint = "hb_get_state2", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_get_state2(ref hb_handle_s param0, ref hb_state_s param1); + + + /// Return Type: int + ///param0: hb_handle_t* + [DllImport("hb.dll", EntryPoint = "hb_get_scancount", CallingConvention = CallingConvention.Cdecl)] + public static extern int hb_get_scancount(ref hb_handle_s param0); + + + /// Return Type: void + ///param0: hb_handle_t** + [DllImport("hb.dll", EntryPoint = "hb_close", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_close(IntPtr hbHandle); + + [DllImport("hb.dll", EntryPoint = "hb_global_close", CallingConvention = CallingConvention.Cdecl)] + public static extern void hb_global_close(); + + [DllImport("hb.dll", EntryPoint = "hb_subtitle_add", CallingConvention = CallingConvention.Cdecl)] + public static extern int hb_subtitle_add(ref hb_job_s job, ref hb_subtitle_config_s subtitleConfig, int track); + + [DllImport("hb.dll", EntryPoint = "hb_srt_add", CallingConvention = CallingConvention.Cdecl)] + public static extern int hb_srt_add(ref hb_job_s job, ref hb_subtitle_config_s subtitleConfig, string lang); + + [DllImport("hb.dll", EntryPoint = "hb_get_default_mixdown", CallingConvention = CallingConvention.Cdecl)] + public static extern int hb_get_default_mixdown(uint codec, int layout); + + [DllImport("hb.dll", EntryPoint = "hb_get_best_mixdown", CallingConvention = CallingConvention.Cdecl)] + public static extern int hb_get_best_mixdown(uint codec, int layout, int mixdown); + + [DllImport("hb.dll", EntryPoint = "hb_get_best_audio_bitrate", CallingConvention = CallingConvention.Cdecl)] + public static extern int hb_get_best_audio_bitrate(uint codec, int bitrate, int samplerate, int mixdown); + + [DllImport("hb.dll", EntryPoint = "hb_get_audio_bitrate_limits", CallingConvention = CallingConvention.Cdecl)] + public static extern int hb_get_audio_bitrate_limits(uint codec, int samplerate, int mixdown, ref int low, ref int high); + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/Misc.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/Misc.cs new file mode 100644 index 000000000..7d742f6c9 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/Misc.cs @@ -0,0 +1,415 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; + +namespace HandBrake.Interop +{ + [StructLayout(LayoutKind.Sequential)] + public struct hb_anamorphic_substruct + { + /// int + public int mode; + + /// int + public int itu_par; + + /// int + public int par_width; + + /// int + public int par_height; + + /// int + public int dar_width; + + /// int + public int dar_height; + + /// int + public int keep_display_aspect; + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_list_s + { + /// void** + public IntPtr items; + + /// int + public int items_alloc; + + /// int + public int items_count; + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_rate_s + { + /// char* + [MarshalAs(UnmanagedType.LPStr)] + public string @string; + + /// int + public int rate; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct hb_metadata_s + { + /// char[255] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)] + public string name; + + /// char[255] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)] + public string artist; + + /// char[255] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)] + public string composer; + + /// char[255] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)] + public string release_date; + + /// char[1024] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string comment; + + /// char[255] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)] + public string album; + + /// char[255] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)] + public string genre; + + /// uint32_t->unsigned int + public uint coverart_size; + + /// uint8_t* + public IntPtr coverart; + } + + public enum hb_title_type_anon + { + HB_DVD_TYPE, + + HB_BD_TYPE, + + HB_STREAM_TYPE, + + HB_FF_STREAM_TYPE, + } + + public enum Anonymous_618ebeca_0ad9_4a71_9a49_18e50ac2e9db + { + /// HB_MPEG2_PS_DEMUXER -> 0 + HB_MPEG2_PS_DEMUXER = 0, + + HB_MPEG2_TS_DEMUXER, + + HB_NULL_DEMUXER, + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_state_scanning_anon + { + /// int + public int title_cur; + + /// int + public int title_count; + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_state_working_anon + { + /// float + public float progress; + + /// int + public int job_cur; + + /// int + public int job_count; + + /// float + public float rate_cur; + + /// float + public float rate_avg; + + /// int + public int hours; + + /// int + public int minutes; + + /// int + public int seconds; + + /// int + public int sequence_id; + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_state_workdone_anon + { + /// int + public int error; + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_state_muxing_anon + { + /// float + public float progress; + } + + [StructLayout(LayoutKind.Explicit)] + public struct hb_state_param_u + { + [FieldOffset(0)] + public hb_state_scanning_anon scanning; + + [FieldOffset(0)] + public hb_state_working_anon working; + + [FieldOffset(0)] + public hb_state_workdone_anon workdone; + + [FieldOffset(0)] + public hb_state_muxing_anon muxing; + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_state_s + { + /// int + public int state; + public hb_state_param_u param; + } + + [StructLayout(LayoutKind.Explicit)] + public struct Anonymous_a0a59d69_d9a4_4003_a198_f7c51511e31d + { + /// int + [FieldOffset(0)] + public int ac3; + + /// int + [FieldOffset(0)] + public int dca; + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_mixdown_s + { + /// char* + [MarshalAs(UnmanagedType.LPStr)] + public string human_readable_name; + + /// char* + [MarshalAs(UnmanagedType.LPStr)] + public string internal_name; + + /// char* + [MarshalAs(UnmanagedType.LPStr)] + public string short_name; + + /// int + public int amixdown; + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_fifo_s + { + /// hb_lock_t* + public IntPtr @lock; + + /// uint32_t->unsigned int + public uint capacity; + + /// uint32_t->unsigned int + public uint size; + + /// uint32_t->unsigned int + public uint buffer_size; + + /// hb_buffer_t* + public IntPtr first; + + /// hb_buffer_t* + public IntPtr last; + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_lock_s + { + } + + // Only called by detect_comb at the moment + [StructLayout(LayoutKind.Sequential)] + public struct hb_buffer_s + { + /// int + public int size; + + /// int + public int alloc; + + /// uint8_t* + [MarshalAs(UnmanagedType.LPStr)] + public string data; + + /// int + public int cur; + + /// int64_t->int + public long sequence; + + public hb_buffer_type_anon type; + + /// int + public int id; + + /// int64_t->int + public long start; + + /// int64_t->int + public long stop; + + public long pcr; + + public byte discontinuity; + + /// int + public int new_chap; + + /// uint8_t->unsigned char + public byte frametype; + + // Given uint by default, probably should be ushort? + /// uint16_t->unsigned int + public uint flags; + + /// int64_t->int + public long renderOffset; + + /// int + public int x; + + /// int + public int y; + + /// int + public int width; + + /// int + public int height; + + /// hb_buffer_t* + public IntPtr sub; + + /// hb_buffer_t* + public IntPtr next; + } + + public enum hb_buffer_type_anon + { + AUDIO_BUF, + + VIDEO_BUF, + + SUBTITLE_BUF, + + OTHER_BUF + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_mux_data_s + { + /// MP4TrackId->uint32_t->unsigned int + public uint track; + + /// uint8_t->unsigned char + public byte subtitle; + + /// int + public int sub_format; + + /// uint64_t->unsigned int + public ulong sum_dur; + } + + // Not referred to anywhere + [StructLayout(LayoutKind.Sequential)] + public struct hb_interjob_s + { + /// int + public int last_job; + + /// int + public int frame_count; + + public int out_frame_count; + + /// uint64_t->unsigned int + public ulong total_time; + + /// int + public int vrate; + + /// int + public int vrate_base; + + /// hb_subtitle_t* + public IntPtr select_subtitle; + } + + /// Return Type: void + ///param0: void* + public delegate void hb_thread_s_function(IntPtr param0); + + [StructLayout(LayoutKind.Sequential)] + public struct hb_thread_s + { + /// char* + [MarshalAs(UnmanagedType.LPStr)] + public string name; + + /// int + public int priority; + + /// hb_thread_s_function + public hb_thread_s_function AnonymousMember1; + + /// void* + public IntPtr arg; + + /// hb_lock_t* + public IntPtr @lock; + + /// int + public int exited; + + /// pthread_t->ptw32_handle_t->Anonymous_55c509b5_bbf2_4788_a684_ac1bd0056655 + public ptw32_handle_t thread; + } + + [StructLayout(LayoutKind.Sequential)] + public struct ptw32_handle_t + { + /// void* + public IntPtr p; + + /// unsigned int + public uint x; + } + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void LoggingCallback(string message); +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/NativeConstants.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/NativeConstants.cs new file mode 100644 index 000000000..8d097b33e --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/NativeConstants.cs @@ -0,0 +1,99 @@ +namespace HandBrake.Interop +{ + public partial class NativeConstants + { + public const int HB_ACODEC_MASK = 0x0000FF00; + public const int HB_ACODEC_FAAC = 0x00000100; + public const int HB_ACODEC_LAME = 0x00000200; + public const int HB_ACODEC_VORBIS = 0x00000400; + public const int HB_ACODEC_AC3 = 0x00000800; + public const int HB_ACODEC_MPGA = 0x00001000; + public const int HB_ACODEC_LPCM = 0x00002000; + public const int HB_ACODEC_DCA = 0x00004000; + public const int HB_ACODEC_FFMPEG = 0x00008000; + public const int HB_ACODEC_CA_AAC = 0x00010000; + public const int HB_ACODEC_PASS_FLAG = 0x40000000; + public const int HB_ACODEC_PASS_MASK = HB_ACODEC_AC3 | HB_ACODEC_DCA; + public const int HB_ACODEC_AC3_PASS = HB_ACODEC_AC3 | HB_ACODEC_PASS_FLAG; + public const int HB_ACODEC_DCA_PASS = HB_ACODEC_DCA | HB_ACODEC_PASS_FLAG; + public const int HB_ACODEC_ANY = HB_ACODEC_MASK | HB_ACODEC_PASS_FLAG; + + public const int HB_SUBSTREAM_BD_TRUEHD = 0x72; + public const int HB_SUBSTREAM_BD_AC3 = 0x76; + public const int HB_SUBSTREAM_BD_DTSHD = 0x72; + public const int HB_SUBSTREAM_BD_DTS = 0x71; + + public const int HB_AMIXDOWN_DCA_FORMAT_MASK = 0x00FFF000; + public const int HB_AMIXDOWN_A52_FORMAT_MASK = 0x00000FF0; + public const int HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK = 0x0000000F; + public const int HB_AMIXDOWN_MONO = 0x01000001; + public const int HB_AMIXDOWN_STEREO = 0x02002022; + public const int HB_AMIXDOWN_DOLBY = 0x042070A2; + public const int HB_AMIXDOWN_DOLBYPLII = 0x084094A2; + public const int HB_AMIXDOWN_6CH = 0x10089176; + + public const int HB_INPUT_CH_LAYOUT_MONO = 0x0110010; + public const int HB_INPUT_CH_LAYOUT_STEREO = 0x0220020; + public const int HB_INPUT_CH_LAYOUT_DOLBY = 0x0320031; + public const int HB_INPUT_CH_LAYOUT_3F = 0x0430030; + public const int HB_INPUT_CH_LAYOUT_2F1R = 0x0521021; + public const int HB_INPUT_CH_LAYOUT_3F1R = 0x0631031; + public const int HB_INPUT_CH_LAYOUT_2F2R = 0x0722022; + public const int HB_INPUT_CH_LAYOUT_3F2R = 0x0832032; + public const int HB_INPUT_CH_LAYOUT_4F2R = 0x0942042; + public const int HB_INPUT_CH_LAYOUT_3F4R = 0x0a34034; + public const int HB_INPUT_CH_LAYOUT_HAS_LFE = 0x0000100; + public const int HB_INPUT_CH_LAYOUT_DISCRETE_FRONT_MASK = 0x00F0000; + public const int HB_INPUT_CH_LAYOUT_DISCRETE_REAR_MASK = 0x000F000; + public const int HB_INPUT_CH_LAYOUT_DISCRETE_LFE_MASK = 0x0000F00; + public const int HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK = 0xFFFF0FF; + public const int HB_INPUT_CH_LAYOUT_ENCODED_FRONT_MASK = 0x00000F0; + public const int HB_INPUT_CH_LAYOUT_ENCODED_REAR_MASK = 0x000000F; + + public const int HB_VCODEC_MASK = 0x0000FF; + public const int HB_VCODEC_X264 = 0x000001; + public const int HB_VCODEC_THEORA = 0x000002; + public const int HB_VCODEC_FFMPEG_MPEG4 = 0x000010; + public const int HB_VCODEC_FFMPEG = HB_VCODEC_FFMPEG_MPEG4; + public const int HB_VCODEC_FFMPEG_MPEG2 = 0x000020; + public const int HB_VCODEC_FFMPEG_MASK = 0x0000F0; + + public const int HB_MUX_MASK = 0xFF0000; + public const int HB_MUX_MP4 = 0x010000; + public const int HB_MUX_MKV = 0x200000; + + public const int HBTF_NO_IDR = 1 << 0; + + public const int HB_STATE_IDLE = 1; + public const int HB_STATE_SCANNING = 2; + public const int HB_STATE_SCANDONE = 4; + public const int HB_STATE_WORKING = 8; + public const int HB_STATE_PAUSED = 16; + public const int HB_STATE_WORKDONE = 32; + public const int HB_STATE_MUXING = 64; + + public const int HB_ERROR_NONE = 0; + public const int HB_ERROR_CANCELED = 1; + public const int HB_ERROR_UNKNOWN = 2; + + public const int AUDIO_F_DOLBY = 1 << 31; + + public const int HB_FRAME_IDR = 0x01; + public const int HB_FRAME_I = 0x02; + public const int HB_FRAME_AUDIO = 0x04; + public const int HB_FRAME_P = 0x10; + public const int HB_FRAME_B = 0x20; + public const int HB_FRAME_BREF = 0x40; + public const int HB_FRAME_KEY = 0x0F; + public const int HB_FRAME_REF = 0xF0; + + public const int HB_CONFIG_MAX_SIZE = 8192; + + public const int HB_FILTER_DETELECINE = 1; + public const int HB_FILTER_DEINTERLACE = 2; + public const int HB_FILTER_DEBLOCK = 3; + public const int HB_FILTER_DENOISE = 4; + public const int HB_FILTER_DECOMB = 5; + public const int HB_FILTER_ROTATE = 6; + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_audio.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_audio.cs new file mode 100644 index 000000000..6992d1ffd --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_audio.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace HandBrake.Interop +{ + [StructLayout(LayoutKind.Sequential)] + public struct hb_audio_s + { + /// int + public int id; + + /// hb_audio_config_t->hb_audio_config_s + public hb_audio_config_s config; + + // Padding for the part of the struct we don't care about marshaling. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = MarshalingConstants.AudioPaddingBytes, ArraySubType = UnmanagedType.U1)] + public byte[] padding; + + /// Anonymous_e6c7b779_b5a3_4e80_9fa8_13619d14f545 + //public Anonymous_e6c7b779_b5a3_4e80_9fa8_13619d14f545 priv; + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_audio_config_s + { + public hb_audio_config_output_s output; + public hb_audio_config_input_s input; + + /// Anonymous_a0a59d69_d9a4_4003_a198_f7c51511e31d + public Anonymous_a0a59d69_d9a4_4003_a198_f7c51511e31d flags; + + public hb_audio_config_lang_s lang; + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_audio_config_output_s + { + /// int + public int track; + + /// uint32_t->unsigned int + public uint codec; + + /// int + public int samplerate; + + /// int + public int bitrate; + + /// int + public int mixdown; + + /// double + public double dynamic_range_compression; + + public double gain; + + /// char* + //[MarshalAs(UnmanagedType.LPStr)] + //public string name; + + public IntPtr name; + } + + [StructLayout(LayoutKind.Sequential)] + public struct hb_audio_config_input_s + { + /// int + public int track; + + /// uint32_t->unsigned int + public uint codec; + + public uint reg_desc; + + public uint stream_type; + + public uint substream_type; + + /// uint32_t->unsigned int + public uint codec_param; + + /// uint32_t->unsigned int + public uint version; + + /// uint32_t->unsigned int + public uint mode; + + /// int + public int samplerate; + + /// int + public int bitrate; + + /// int + public int channel_layout; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct hb_audio_config_lang_s + { + /// char[1024] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string description; + + /// char[1024] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string simple; + + /// char[4] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string iso639_2; + + /// uint8_t->unsigned char + public byte type; + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_chapter_s.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_chapter_s.cs new file mode 100644 index 000000000..fd3762398 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_chapter_s.cs @@ -0,0 +1,48 @@ +using System.Runtime.InteropServices; + +namespace HandBrake.Interop +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct hb_chapter_s + { + /// int + public int index; + + /// int + public int pgcn; + + /// int + public int pgn; + + /// int + public int cell_start; + + /// int + public int cell_end; + + /// int + public ulong block_start; + + /// int + public ulong block_end; + + /// int + public ulong block_count; + + /// int + public int hours; + + /// int + public int minutes; + + /// int + public int seconds; + + /// uint64_t->unsigned int + public ulong duration; + + /// char[1024] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string title; + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_handle_s.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_handle_s.cs new file mode 100644 index 000000000..dd56681bb --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_handle_s.cs @@ -0,0 +1,78 @@ +using System; +using System.Runtime.InteropServices; + +namespace HandBrake.Interop +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct hb_handle_s + { + public int id; + + /// int + public int build; + + /// char[32] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] + public string version; + + /// hb_thread_t* + public IntPtr update_thread; + + /// int + public int die; + + /// hb_thread_t* + public IntPtr main_thread; + + /// int + public int pid; + + /// hb_list_t* + public IntPtr list_title; + + /// hb_thread_t* + public IntPtr scan_thread; + + /// hb_list_t* + public IntPtr jobs; + + /// hb_job_t* + public IntPtr current_job; + + /// int + public int job_count; + + /// int + public int job_count_permanent; + + /// int + public int work_die; + + /// int + public int work_error; + + /// hb_thread_t* + public IntPtr work_thread; + + // This is REMOVED in the latest HB SVN + public int cpu_count; + + /// hb_lock_t* + public IntPtr state_lock; + + /// hb_state_t->hb_state_s + public hb_state_s state; + + /// int + public int paused; + + /// hb_lock_t* + public IntPtr pause_lock; + + /// int + public int scanCount; + + /// hb_interjob_t* + public IntPtr interjob; + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_job_s.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_job_s.cs new file mode 100644 index 000000000..c12352e04 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_job_s.cs @@ -0,0 +1,149 @@ +using System; +using System.Runtime.InteropServices; + +namespace HandBrake.Interop +{ + [StructLayout(LayoutKind.Sequential)] + public struct hb_job_s + { + /// int + public int sequence_id; + + /// hb_title_t* + public IntPtr title; + + public int feature; + + /// int + public int chapter_start; + + /// int + public int chapter_end; + + /// int + public int chapter_markers; + + /// int[4] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.I4)] + public int[] crop; + + /// int + public int deinterlace; + + /// hb_list_t* + public IntPtr filters; + + /// int + public int width; + + /// int + public int height; + + /// int + public int keep_ratio; + + /// int + public int grayscale; + + public hb_anamorphic_substruct anamorphic; + + public int modulus; + + /// int + public int maxWidth; + + /// int + public int maxHeight; + + /// int + public int vcodec; + + /// float + public float vquality; + + /// int + public int vbitrate; + + public int pfr_vrate; + + public int pfr_vrate_base; + + /// int + public int vrate; + + /// int + public int vrate_base; + + /// int + public int cfr; + + /// int + public int pass; + + /// char* + //[MarshalAs(UnmanagedType.LPStr)] + //public string x264opts; + + public IntPtr advanced_opts; + + /// int + public int areBframes; + + /// int + public int color_matrix; + + /// hb_list_t* + public IntPtr list_audio; + + /// hb_list_t* + public IntPtr list_subtitle; + + /// int + public int mux; + + /// char* + [MarshalAs(UnmanagedType.LPStr)] + public string file; + + /// int + public int largeFileSize; + + /// int + public int mp4_optimize; + + /// int + public int ipod_atom; + + /// int + public int indepth_scan; + + /// hb_subtitle_config_t->hb_subtitle_config_s + public hb_subtitle_config_s select_subtitle_config; + + /// int + public int angle; + + public int frame_to_start; + + public long pts_to_start; + + /// int + public int frame_to_stop; + + /// int64_t->int + public long pts_to_stop; + + /// int + public int start_at_preview; + + /// int + public int seek_points; + + /// uint32_t->unsigned int + public uint frames_to_skip; + + // Padding for the part of the struct we don't care about marshaling. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = MarshalingConstants.JobPaddingBytes, ArraySubType = UnmanagedType.U1)] + public byte[] padding; + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_subtitle.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_subtitle.cs new file mode 100644 index 000000000..f5a830cc4 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_subtitle.cs @@ -0,0 +1,122 @@ +using System; +using System.Runtime.InteropServices; + +namespace HandBrake.Interop +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct hb_subtitle_s + { + /// int + public int id; + + /// int + public int track; + + /// hb_subtitle_config_t->hb_subtitle_config_s + public hb_subtitle_config_s config; + + /// hb_subtitle_s_subtype + public hb_subtitle_s_subtype format; + + /// hb_subtitle_s_subsource + public hb_subtitle_s_subsource source; + + /// char[1024] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string lang; + + /// char[4] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string iso639_2; + + /// uint8_t->unsigned char + public byte type; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16, ArraySubType = UnmanagedType.U4)] + public uint[] palette; + + public int width; + + public int height; + + public IntPtr extradata; + + public int extradata_size; + + /// int + public int hits; + + /// int + public int forced_hits; + + /// hb_fifo_t* + public IntPtr fifo_in; + + /// hb_fifo_t* + public IntPtr fifo_raw; + + /// hb_fifo_t* + public IntPtr fifo_sync; + + /// hb_fifo_t* + public IntPtr fifo_out; + + /// hb_mux_data_t* + public IntPtr mux_data; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct hb_subtitle_config_s + { + /// hb_subtitle_config_s_subdest + public hb_subtitle_config_s_subdest dest; + + /// int + public int force; + + /// int + public int default_track; + + /// char[128] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string src_filename; + + /// char[40] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)] + public string src_codeset; + + /// int64_t->int + public long offset; + } + + public enum hb_subtitle_config_s_subdest + { + RENDERSUB, + + PASSTHRUSUB, + } + + public enum hb_subtitle_s_subtype + { + PICTURESUB, + + TEXTSUB, + } + + public enum hb_subtitle_s_subsource + { + VOBSUB, + + SRTSUB, + + CC608SUB, + + CC708SUB, + + UTF8SUB, + + TX3GSUB, + + SSASUB + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_title_s.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_title_s.cs new file mode 100644 index 000000000..856cdcfbb --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_title_s.cs @@ -0,0 +1,145 @@ +using System; +using System.Runtime.InteropServices; + +namespace HandBrake.Interop +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct hb_title_s + { + /// Anonymous_990d28ea_6cf3_4fbc_8143_4df9513e9550 + public hb_title_type_anon type; + + public uint reg_desc; + + /// char[1024] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string dvd; + + /// char[1024] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string name; + + /// int + public int index; + + /// int + public int vts; + + /// int + public int ttn; + + /// int + public int cell_start; + + /// int + public int cell_end; + + /// int + public ulong block_start; + + /// int + public ulong block_end; + + /// int + public ulong block_count; + + /// int + public int angle_count; + + /// int + public int hours; + + /// int + public int minutes; + + /// int + public int seconds; + + /// uint64_t->unsigned int + public ulong duration; + + /// double + public double aspect; + + /// double + public double container_aspect; + + /// int + public int width; + + /// int + public int height; + + /// int + public int pixel_aspect_width; + + /// int + public int pixel_aspect_height; + + /// int + public int rate; + + /// int + public int rate_base; + + /// int[4] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.I4)] + public int[] crop; + + //public fixed int crop[4]; + + /// Anonymous_618ebeca_0ad9_4a71_9a49_18e50ac2e9db + public Anonymous_618ebeca_0ad9_4a71_9a49_18e50ac2e9db demuxer; + + /// int + public int detected_interlacing; + + public int pcr_pid; + + /// int + public int video_id; + + /// int + public int video_codec; + + public uint video_stream_type; + + /// int + public int video_codec_param; + + /// char* + [MarshalAs(UnmanagedType.LPStr)] + public string video_codec_name; + + /// int + public int video_bitrate; + + /// char* + [MarshalAs(UnmanagedType.LPStr)] + public string container_name; + + /// int + public int data_rate; + + /// hb_metadata_t* + public IntPtr metadata; + + /// hb_list_t* + public IntPtr list_chapter; + + /// hb_list_t* + public IntPtr list_audio; + + /// hb_list_t* + public IntPtr list_subtitle; + + /// hb_list_t* + public IntPtr list_attachment; + + /// hb_job_t* + public IntPtr job; + + /// uint32_t->unsigned int + public uint flags; + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/InteropUtilities.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/InteropUtilities.cs new file mode 100644 index 000000000..4102e5eb7 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/InteropUtilities.cs @@ -0,0 +1,144 @@ +namespace HandBrake.Interop +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Runtime.InteropServices; + + /// <summary> + /// Helper utilities for native interop. + /// </summary> + public static class InteropUtilities + { + /// <summary> + /// Reads the given native structure pointer. + /// </summary> + /// <typeparam name="T">The type to convert the structure to.</typeparam> + /// <param name="structPtr">The pointer to the native structure.</param> + /// <returns>The converted structure.</returns> + public static T ReadStructure<T>(IntPtr structPtr) + { + return (T)Marshal.PtrToStructure(structPtr, typeof(T)); + } + + /// <summary> + /// Converts the given native HandBrake list to a managed list. + /// </summary> + /// <typeparam name="T">The type of structure in the list.</typeparam> + /// <param name="listPtr">The pointer to the native list.</param> + /// <returns>The converted managed list.</returns> + public static List<T> ConvertList<T>(IntPtr listPtr) + { + List<T> returnList = new List<T>(); + hb_list_s itemList = ReadStructure<hb_list_s>(listPtr); + + for (int i = 0; i < itemList.items_count; i++) + { + IntPtr itemPtr = Marshal.ReadIntPtr(itemList.items, i * Marshal.SizeOf(typeof(IntPtr))); + returnList.Add(ReadStructure<T>(itemPtr)); + } + + return returnList; + } + + /// <summary> + /// Creats a new, empty native HandBrake list. + /// </summary> + /// <returns>The new native list.</returns> + public static NativeList CreateNativeList(int capacity) + { + NativeList returnList = new NativeList(); + int intSize = Marshal.SizeOf(typeof(IntPtr)); + + IntPtr nativeListInternal = Marshal.AllocHGlobal(capacity * intSize); + returnList.AllocatedMemory.Add(nativeListInternal); + + hb_list_s nativeListStruct = new hb_list_s(); + nativeListStruct.items = nativeListInternal; + nativeListStruct.items_alloc = capacity; + nativeListStruct.items_count = 0; + + IntPtr nativeListStructPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(hb_list_s))); + Marshal.StructureToPtr(nativeListStruct, nativeListStructPtr, false); + + returnList.ListPtr = nativeListStructPtr; + return returnList; + } + + /// <summary> + /// Creates a native HandBrake list from the given managed list of pointers. + /// </summary> + /// <param name="list">The managed list to convert.</param> + /// <returns>The converted native list.</returns> + public static NativeList CreateIntPtrList(List<IntPtr> list) + { + NativeList returnList = new NativeList(); + int intSize = Marshal.SizeOf(typeof(IntPtr)); + + IntPtr nativeListInternal = Marshal.AllocHGlobal(list.Count * intSize); + returnList.AllocatedMemory.Add(nativeListInternal); + for (int i = 0; i < list.Count; i++) + { + Marshal.WriteIntPtr(nativeListInternal, i * intSize, list[i]); + } + + hb_list_s nativeListStruct = new hb_list_s(); + nativeListStruct.items = nativeListInternal; + nativeListStruct.items_alloc = list.Count; + nativeListStruct.items_count = list.Count; + + IntPtr nativeListStructPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(hb_list_s))); + Marshal.StructureToPtr(nativeListStruct, nativeListStructPtr, false); + + returnList.ListPtr = nativeListStructPtr; + return returnList; + } + + /// <summary> + /// Creates a native HandBrake list from the given managed list of structures. + /// </summary> + /// <typeparam name="T">The type of structures in the list.</typeparam> + /// <param name="list">The managed list to convert.</param> + /// <returns>The converted native list.</returns> + public static NativeList ConvertListBack<T>(List<T> list) + { + NativeList returnList = new NativeList(); + int intSize = Marshal.SizeOf(typeof(IntPtr)); + + IntPtr nativeListInternal = Marshal.AllocHGlobal(list.Count * intSize); + returnList.AllocatedMemory.Add(nativeListInternal); + for (int i = 0; i < list.Count; i++) + { + IntPtr itemPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(T))); + returnList.AllocatedMemory.Add(itemPtr); + Marshal.StructureToPtr(list[i], itemPtr, false); + + Marshal.WriteIntPtr(nativeListInternal, i * intSize, itemPtr); + } + + hb_list_s nativeListStruct = new hb_list_s(); + nativeListStruct.items = nativeListInternal; + nativeListStruct.items_alloc = list.Count; + nativeListStruct.items_count = list.Count; + + IntPtr nativeListStructPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(hb_list_s))); + Marshal.StructureToPtr(nativeListStruct, nativeListStructPtr, false); + + returnList.ListPtr = nativeListStructPtr; + return returnList; + } + + /// <summary> + /// Frees all the memory locations in the given list. + /// </summary> + /// <param name="memoryList">The list of memory locations to free.</param> + public static void FreeMemory(List<IntPtr> memoryList) + { + foreach (IntPtr memoryLocation in memoryList) + { + Marshal.FreeHGlobal(memoryLocation); + } + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Language.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Language.cs new file mode 100644 index 000000000..2bc4ff329 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Language.cs @@ -0,0 +1,38 @@ +namespace HandBrake.Interop +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + /// <summary> + /// Represents a language. + /// </summary> + public class Language + { + /// <summary> + /// Initializes a new instance of the Language class. + /// </summary> + /// <param name="code">The code for the langauge.</param> + public Language(string code) + { + this.Code = code; + } + + /// <summary> + /// Gets the friendly name of the language. + /// </summary> + public string Name + { + get + { + return LanguageCodes.Decode(this.Code); + } + } + + /// <summary> + /// Gets or sets the language code. + /// </summary> + public string Code { get; set; } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/LanguageCodes.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/LanguageCodes.cs new file mode 100644 index 000000000..2e0bac7b4 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/LanguageCodes.cs @@ -0,0 +1,255 @@ +namespace HandBrake.Interop +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + /// <summary> + /// Contains utilities for converting language codes. + /// </summary> + public static class LanguageCodes + { + /// <summary> + /// The map of language codes to friendly names. + /// </summary> + private static Dictionary<string, string> languageMap; + + /// <summary> + /// Gets the map of language codes to friendly names. + /// </summary> + private static Dictionary<string, string> LanguageMap + { + get + { + if (languageMap == null) + { + languageMap = new Dictionary<string, string> + { + {"und", "Unspecified"}, + {"eng", "English"}, + {"deu", "Deutsch"}, + {"fra", "Français"}, + {"spa", "Español"}, + {"rus", "Russian"}, + {"aar", "Afar"}, + {"abk", "Abkhazian"}, + {"afr", "Afrikaans"}, + {"aka", "Akan"}, + {"sqi", "Albanian"}, + {"amh", "Amharic"}, + {"ara", "Arabic"}, + {"arg", "Aragonese"}, + {"hye", "Armenian"}, + {"asm", "Assamese"}, + {"ava", "Avaric"}, + {"ave", "Avestan"}, + {"aym", "Aymara"}, + {"aze", "Azerbaijani"}, + {"bak", "Bashkir"}, + {"bam", "Bambara"}, + {"eus", "Basque"}, + {"bel", "Belarusian"}, + {"ben", "Bengali"}, + {"bih", "Bihari"}, + {"bis", "Bislama"}, + {"bos", "Bosnian"}, + {"bre", "Breton"}, + {"bul", "Bulgarian"}, + {"mya", "Burmese"}, + {"cat", "Catalan"}, + {"cha", "Chamorro"}, + {"che", "Chechen"}, + {"zho", "Chinese"}, + {"chu", "Church Slavic"}, + {"chv", "Chuvash"}, + {"cor", "Cornish"}, + {"cos", "Corsican"}, + {"cre", "Cree"}, + {"ces", "Czech"}, + {"dan", "Dansk"}, + {"div", "Divehi"}, + {"nld", "Nederlands"}, + {"dzo", "Dzongkha"}, + {"epo", "Esperanto"}, + {"est", "Estonian"}, + {"ewe", "Ewe"}, + {"fao", "Faroese"}, + {"fij", "Fijian"}, + {"fin", "Suomi"}, + {"fry", "Western Frisian"}, + {"ful", "Fulah"}, + {"kat", "Georgian"}, + {"gla", "Gaelic (Scots)"}, + {"gle", "Irish"}, + {"glg", "Galician"}, + {"glv", "Manx"}, + {"ell", "Greek Modern"}, + {"grn", "Guarani"}, + {"guj", "Gujarati"}, + {"hat", "Haitian"}, + {"hau", "Hausa"}, + {"heb", "Hebrew"}, + {"her", "Herero"}, + {"hin", "Hindi"}, + {"hmo", "Hiri Motu"}, + {"hun", "Magyar"}, + {"ibo", "Igbo"}, + {"isl", "Islenska"}, + {"ido", "Ido"}, + {"iii", "Sichuan Yi"}, + {"iku", "Inuktitut"}, + {"ile", "Interlingue"}, + {"ina", "Interlingua"}, + {"ind", "Indonesian"}, + {"ipk", "Inupiaq"}, + {"ita", "Italiano"}, + {"jav", "Javanese"}, + {"jpn", "Japanese"}, + {"kal", "Kalaallisut"}, + {"kan", "Kannada"}, + {"kas", "Kashmiri"}, + {"kau", "Kanuri"}, + {"kaz", "Kazakh"}, + {"khm", "Central Khmer"}, + {"kik", "Kikuyu"}, + {"kin", "Kinyarwanda"}, + {"kir", "Kirghiz"}, + {"kom", "Komi"}, + {"kon", "Kongo"}, + {"kor", "Korean"}, + {"kua", "Kuanyama"}, + {"kur", "Kurdish"}, + {"lao", "Lao"}, + {"lat", "Latin"}, + {"lav", "Latvian"}, + {"lim", "Limburgan"}, + {"lin", "Lingala"}, + {"lit", "Lithuanian"}, + {"ltz", "Luxembourgish"}, + {"lub", "Luba-Katanga"}, + {"lug", "Ganda"}, + {"mkd", "Macedonian"}, + {"mah", "Marshallese"}, + {"mal", "Malayalam"}, + {"mri", "Maori"}, + {"mar", "Marathi"}, + {"msa", "Malay"}, + {"mlg", "Malagasy"}, + {"mlt", "Maltese"}, + {"mol", "Moldavian"}, + {"mon", "Mongolian"}, + {"nau", "Nauru"}, + {"nav", "Navajo"}, + {"nbl", "Ndebele, South"}, + {"nde", "Ndebele, North"}, + {"ndo", "Ndonga"}, + {"nep", "Nepali"}, + {"nno", "Norwegian Nynorsk"}, + {"nob", "Norwegian Bokmål"}, + {"nor", "Norsk"}, + {"nya", "Chichewa; Nyanja"}, + {"oci", "Occitan"}, + {"oji", "Ojibwa"}, + {"ori", "Oriya"}, + {"orm", "Oromo"}, + {"oss", "Ossetian"}, + {"pan", "Panjabi"}, + {"fas", "Persian"}, + {"pli", "Pali"}, + {"pol", "Polish"}, + {"por", "Portugues"}, + {"pus", "Pushto"}, + {"que", "Quechua"}, + {"roh", "Romansh"}, + {"ron", "Romanian"}, + {"run", "Rundi"}, + {"sag", "Sango"}, + {"san", "Sanskrit"}, + {"srp", "Serbian"}, + {"hrv", "Hrvatski"}, + {"sin", "Sinhala"}, + {"slk", "Slovak"}, + {"slv", "Slovenian"}, + {"sme", "Northern Sami"}, + {"smo", "Samoan"}, + {"sna", "Shona"}, + {"snd", "Sindhi"}, + {"som", "Somali"}, + {"sot", "Sotho Southern"}, + {"srd", "Sardinian"}, + {"ssw", "Swati"}, + {"sun", "Sundanese"}, + {"swa", "Swahili"}, + {"swe", "Svenska"}, + {"tah", "Tahitian"}, + {"tam", "Tamil"}, + {"tat", "Tatar"}, + {"tel", "Telugu"}, + {"tgk", "Tajik"}, + {"tgl", "Tagalog"}, + {"tha", "Thai"}, + {"bod", "Tibetan"}, + {"tir", "Tigrinya"}, + {"ton", "Tonga"}, + {"tsn", "Tswana"}, + {"tso", "Tsonga"}, + {"tuk", "Turkmen"}, + {"tur", "Turkish"}, + {"twi", "Twi"}, + {"uig", "Uighur"}, + {"ukr", "Ukrainian"}, + {"urd", "Urdu"}, + {"uzb", "Uzbek"}, + {"ven", "Venda"}, + {"vie", "Vietnamese"}, + {"vol", "Volapük"}, + {"cym", "Welsh"}, + {"wln", "Walloon"}, + {"wol", "Wolof"}, + {"xho", "Xhosa"}, + {"yid", "Yiddish"}, + {"yor", "Yoruba"}, + {"zha", "Zhuang"}, + {"zul", "Zulu"} + }; + } + + return languageMap; + } + } + + /// <summary> + /// Gets a list of all languages. + /// </summary> + public static IList<Language> Languages + { + get + { + List<Language> languages = new List<Language>(); + + foreach (string languageCode in LanguageMap.Keys) + { + languages.Add(new Language(languageCode)); + } + + return languages; + } + } + + /// <summary> + /// Gives the friendly name of the language with the given code. + /// </summary> + /// <param name="languageCode">The language code.</param> + /// <returns>The friendly name of the language.</returns> + public static string Decode(string languageCode) + { + if (LanguageMap.ContainsKey(languageCode)) + { + return LanguageMap[languageCode]; + } + + return "Unknown"; + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/MarshalingConstants.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/MarshalingConstants.cs new file mode 100644 index 000000000..67fd8d177 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/MarshalingConstants.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public static class MarshalingConstants + { +#if X64 + public const int JobPaddingBytes = 24696; + public const int AudioPaddingBytes = 24640; +#else + public const int JobPaddingBytes = 24644; + public const int AudioPaddingBytes = 24608; +#endif + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/MessageLoggedEventArgs.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/MessageLoggedEventArgs.cs new file mode 100644 index 000000000..6976fedc6 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/MessageLoggedEventArgs.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public class MessageLoggedEventArgs : EventArgs + { + public string Message { get; set; } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Cropping.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Cropping.cs new file mode 100644 index 000000000..2b95a0e11 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Cropping.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public class Cropping + { + public int Top { get; set; } + public int Bottom { get; set; } + public int Left { get; set; } + public int Right { get; set; } + + public Cropping Clone() + { + return new Cropping + { + Top = this.Top, + Bottom = this.Bottom, + Left = this.Left, + Right = this.Right + }; + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/EncodeJob.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/EncodeJob.cs new file mode 100644 index 000000000..850f6ea2e --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/EncodeJob.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Serialization; + +namespace HandBrake.Interop +{ + public class EncodeJob + { + public SourceType SourceType { get; set; } + public string SourcePath { get; set; } + + /// <summary> + /// Gets or sets the 1-based index of the title to encode. + /// </summary> + public int Title { get; set; } + + /// <summary> + /// Gets or sets the angle to encode. 0 for default, 1+ for specified angle. + /// </summary> + public int Angle { get; set; } + + public VideoRangeType RangeType { get; set; } + public int ChapterStart { get; set; } + public int ChapterEnd { get; set; } + + public double SecondsStart { get; set; } + public double SecondsEnd { get; set; } + + public int FramesStart { get; set; } + public int FramesEnd { get; set; } + + /// <summary> + /// Gets or sets the list of chosen audio tracks (1-based) + /// </summary> + public List<int> ChosenAudioTracks { get; set; } + public Subtitles Subtitles { get; set; } + public bool UseDefaultChapterNames { get; set; } + public List<string> CustomChapterNames { get; set; } + + public string OutputPath { get; set; } + + public EncodingProfile EncodingProfile { get; set; } + + // The length of video to encode. + [XmlIgnore] + public TimeSpan Length { get; set; } + + [XmlElement("Length")] + public string XmlLength + { + get { return this.Length.ToString(); } + set { this.Length = TimeSpan.Parse(value); } + } + + public EncodeJob Clone() + { + EncodeJob clone = new EncodeJob + { + SourceType = this.SourceType, + SourcePath = this.SourcePath, + Title = this.Title, + Angle = this.Angle, + RangeType = this.RangeType, + ChapterStart = this.ChapterStart, + ChapterEnd = this.ChapterEnd, + SecondsStart = this.SecondsStart, + SecondsEnd = this.SecondsEnd, + FramesStart = this.FramesStart, + FramesEnd = this.FramesEnd, + ChosenAudioTracks = new List<int>(this.ChosenAudioTracks), + Subtitles = this.Subtitles, + UseDefaultChapterNames = this.UseDefaultChapterNames, + OutputPath = this.OutputPath, + EncodingProfile = this.EncodingProfile, + Length = this.Length + }; + + return clone; + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Anamorphic.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Anamorphic.cs new file mode 100644 index 000000000..b6d3d110f --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Anamorphic.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public enum Anamorphic + { + [Display(Name = "None")] + None = 0, + [Display(Name = "Strict")] + Strict, + [Display(Name = "Loose")] + Loose, + [Display(Name = "Custom")] + Custom + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoder.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoder.cs new file mode 100644 index 000000000..159ed7c30 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoder.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public enum AudioEncoder + { + [Display(Name = "AAC (faac)")] + Faac = 0, + + [Display(Name = "MP3 (lame)")] + Lame, + + [Display(Name = "AC3 (ffmpeg)")] + Ac3, + + [Display(Name = "Passthrough (AC3/DTS)")] + Passthrough, + + [Display(Name = "Passthrough (AC3)")] + Ac3Passthrough, + + [Display(Name = "Passthrough (DTS)")] + DtsPassthrough, + + [Display(Name = "Vorbis (vorbis)")] + Vorbis + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoding.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoding.cs new file mode 100644 index 000000000..0821749b5 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoding.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public class AudioEncoding + { + public int InputNumber { get; set; } + public AudioEncoder Encoder { get; set; } + + /// <summary> + /// Gets or sets the bitrate (in kbps) of this track. + /// </summary> + public int Bitrate { get; set; } + public Mixdown Mixdown { get; set; } + + /// <summary> + /// Obsolete. Use SampleRateRaw instead. + /// </summary> + [Obsolete("This property is ignored and only exists for backwards compatibility. Use SampleRateRaw instead.")] + public string SampleRate { get; set; } + + /// <summary> + /// Gets or sets the sample rate in Hz. + /// </summary> + public int SampleRateRaw { get; set; } + + public int Gain { get; set; } + public double Drc { get; set; } + public string Name { get; set; } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Decomb.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Decomb.cs new file mode 100644 index 000000000..5fa9bda74 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Decomb.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public enum Decomb + { + Off = 0, + Default, + Custom + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Deinterlace.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Deinterlace.cs new file mode 100644 index 000000000..ee08ba10d --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Deinterlace.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public enum Deinterlace + { + Off = 0, + Fast, + Slow, + Slower, + Custom + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Denoise.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Denoise.cs new file mode 100644 index 000000000..7b59ae1b8 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Denoise.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public enum Denoise + { + Off = 0, + Weak, + Medium, + Strong, + Custom + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Detelecine.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Detelecine.cs new file mode 100644 index 000000000..fe9e543c4 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Detelecine.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public enum Detelecine + { + Off = 0, + Default, + Custom + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/EncodingProfile.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/EncodingProfile.cs new file mode 100644 index 000000000..d4275b4d2 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/EncodingProfile.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public class EncodingProfile + { + public EncodingProfile() + { + this.Cropping = new Cropping(); + } + + public OutputFormat OutputFormat { get; set; } + public OutputExtension PreferredExtension { get; set; } + public bool IncludeChapterMarkers { get; set; } + public bool LargeFile { get; set; } + public bool Optimize { get; set; } + public bool IPod5GSupport { get; set; } + + public int Width { get; set; } + public int Height { get; set; } + public int MaxWidth { get; set; } + public int MaxHeight { get; set; } + public bool CustomCropping { get; set; } + public Cropping Cropping { get; set; } + public Anamorphic Anamorphic { get; set; } + public bool UseDisplayWidth { get; set; } + public int DisplayWidth { get; set; } + public bool KeepDisplayAspect { get; set; } + public int PixelAspectX { get; set; } + public int PixelAspectY { get; set; } + public int Modulus { get; set; } + + public Deinterlace Deinterlace { get; set; } + public string CustomDeinterlace { get; set; } + public Decomb Decomb { get; set; } + public string CustomDecomb { get; set; } + public Detelecine Detelecine { get; set; } + public string CustomDetelecine { get; set; } + public Denoise Denoise { get; set; } + public string CustomDenoise { get; set; } + public int Deblock { get; set; } + public bool Grayscale { get; set; } + + public VideoEncoder VideoEncoder { get; set; } + public string X264Options { get; set; } + public VideoEncodeRateType VideoEncodeRateType { get; set; } + public double Quality { get; set; } + public int TargetSize { get; set; } + public int VideoBitrate { get; set; } + public bool TwoPass { get; set; } + public bool TurboFirstPass { get; set; } + public double Framerate { get; set; } + public bool PeakFramerate { get; set; } + + public List<AudioEncoding> AudioEncodings { get; set; } + + public EncodingProfile Clone() + { + EncodingProfile profile = new EncodingProfile + { + OutputFormat = this.OutputFormat, + PreferredExtension = this.PreferredExtension, + IncludeChapterMarkers = this.IncludeChapterMarkers, + LargeFile = this.LargeFile, + Optimize = this.Optimize, + IPod5GSupport = this.IPod5GSupport, + + Width = this.Width, + Height = this.Height, + MaxWidth = this.MaxWidth, + MaxHeight = this.MaxHeight, + CustomCropping = this.CustomCropping, + Cropping = this.Cropping.Clone(), + Anamorphic = this.Anamorphic, + UseDisplayWidth = this.UseDisplayWidth, + DisplayWidth = this.DisplayWidth, + KeepDisplayAspect = this.KeepDisplayAspect, + PixelAspectX = this.PixelAspectX, + PixelAspectY = this.PixelAspectY, + Modulus = this.Modulus, + + Deinterlace = this.Deinterlace, + CustomDeinterlace = this.CustomDeinterlace, + Decomb = this.Decomb, + CustomDecomb = this.CustomDecomb, + Detelecine = this.Detelecine, + CustomDetelecine = this.CustomDetelecine, + Denoise = this.Denoise, + CustomDenoise = this.CustomDenoise, + Deblock = this.Deblock, + Grayscale = this.Grayscale, + + VideoEncoder = this.VideoEncoder, + X264Options = this.X264Options, + VideoEncodeRateType = this.VideoEncodeRateType, + Quality = this.Quality, + TargetSize = this.TargetSize, + VideoBitrate = this.VideoBitrate, + TwoPass = this.TwoPass, + TurboFirstPass = this.TurboFirstPass, + Framerate = this.Framerate, + PeakFramerate = this.PeakFramerate, + + AudioEncodings = new List<AudioEncoding>(this.AudioEncodings) + }; + + return profile; + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Mixdown.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Mixdown.cs new file mode 100644 index 000000000..838c7066b --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Mixdown.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public enum Mixdown + { + [Display(Name = "Dolby Pro Logic II")] + DolbyProLogicII = 0, + + [Display(Name = "Auto")] + Auto, + + [Display(Name = "Mono")] + Mono, + + [Display(Name = "Stereo")] + Stereo, + + [Display(Name = "Dolby Surround")] + DolbySurround, + + [Display(Name = "6 Channel Discrete")] + SixChannelDiscrete + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/OutputExtension.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/OutputExtension.cs new file mode 100644 index 000000000..cd82aab2e --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/OutputExtension.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public enum OutputExtension + { + Mp4, + M4v + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/OutputFormat.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/OutputFormat.cs new file mode 100644 index 000000000..f842fe474 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/OutputFormat.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.ComponentModel; + +namespace HandBrake.Interop +{ + public enum OutputFormat + { + [Display(Name = "MP4")] + Mp4, + [Display(Name = "MKV")] + Mkv + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/VideoEncodeRateType.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/VideoEncodeRateType.cs new file mode 100644 index 000000000..ae08402d4 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/VideoEncodeRateType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public enum VideoEncodeRateType + { + TargetSize = 0, + AverageBitrate, + ConstantQuality + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/VideoEncoder.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/VideoEncoder.cs new file mode 100644 index 000000000..923f446e1 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/VideoEncoder.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public enum VideoEncoder + { + [Display(Name = "H.264 (x264)")] + X264 = 0, + + [Display(Name = "MPEG-4 (FFMpeg)")] + FFMpeg, + + [Display(Name = "VP3 (Theora)")] + Theora + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Limits.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Limits.cs new file mode 100644 index 000000000..9fdc373f5 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Limits.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public class Limits + { + public int Low { get; set; } + + public int High { get; set; } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Size.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Size.cs new file mode 100644 index 000000000..3f9736c86 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Size.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public class Size + { + public Size(int width, int height) + { + this.Width = width; + this.Height = height; + } + + public int Width { get; set; } + public int Height { get; set; } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/SourceSubtitle.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/SourceSubtitle.cs new file mode 100644 index 000000000..e07811cc8 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/SourceSubtitle.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public class SourceSubtitle + { + /// <summary> + /// Gets or sets the 1-based subtitle track number. 0 means foreign audio search. + /// </summary> + public int TrackNumber { get; set; } + public bool Default { get; set; } + public bool Forced { get; set; } + public bool BurnedIn { get; set; } + + public SourceSubtitle Clone() + { + return new SourceSubtitle + { + TrackNumber = this.TrackNumber, + Default = this.Default, + Forced = this.Forced, + BurnedIn = this.BurnedIn + }; + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/SourceType.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/SourceType.cs new file mode 100644 index 000000000..f0a227cad --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/SourceType.cs @@ -0,0 +1,10 @@ +namespace HandBrake.Interop +{ + public enum SourceType + { + None = 0, + File, + VideoFolder, + Dvd + } +} \ No newline at end of file diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/SrtSubtitle.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/SrtSubtitle.cs new file mode 100644 index 000000000..1d80e1f0b --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/SrtSubtitle.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public class SrtSubtitle + { + public bool Default { get; set; } + public string FileName { get; set; } + public string LanguageCode { get; set; } + public string CharacterCode { get; set; } + public int Offset { get; set; } + + public SrtSubtitle Clone() + { + return new SrtSubtitle + { + Default = this.Default, + FileName = this.FileName, + LanguageCode = this.LanguageCode, + CharacterCode = this.CharacterCode, + Offset = this.Offset + }; + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Subtitles.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Subtitles.cs new file mode 100644 index 000000000..a9c1750e0 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Subtitles.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public class Subtitles + { + public List<SrtSubtitle> SrtSubtitles { get; set; } + public List<SourceSubtitle> SourceSubtitles { get; set; } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/VideoRangeType.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/VideoRangeType.cs new file mode 100644 index 000000000..d0e967fbc --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/VideoRangeType.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.ComponentModel.DataAnnotations; + +namespace HandBrake.Interop +{ + public enum VideoRangeType + { + [Display(Name = "Chapters")] + Chapters, + + [Display(Name = "Seconds")] + Seconds, + + [Display(Name = "Frames")] + Frames + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/NativeList.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/NativeList.cs new file mode 100644 index 000000000..6d39bb8f4 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/NativeList.cs @@ -0,0 +1,34 @@ +namespace HandBrake.Interop +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + /// <summary> + /// Represents a HandBrake style native list. + /// </summary> + public class NativeList + { + /// <summary> + /// The list of native memory locations allocated for this list. + /// </summary> + private List<IntPtr> allocatedMemory = new List<IntPtr>(); + + /// <summary> + /// Gets or sets the pointer to the native list. + /// </summary> + public IntPtr ListPtr { get; set; } + + /// <summary> + /// Gets the list of native memory locations allocated for this list. + /// </summary> + public List<IntPtr> AllocatedMemory + { + get + { + return allocatedMemory; + } + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Properties/AssemblyInfo.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..7e74d7e2a --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("HandBrakeInterop")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("HandBrake Team")] +[assembly: AssemblyProduct("HandBrake.Interop")] +[assembly: AssemblyCopyright("Copyright © HandBrake Team 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("cc59844b-9e1b-4854-8b92-3b24c646aee5")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.18.0.0")] +[assembly: AssemblyFileVersion("1.18.0.0")] diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/ScanProgressEventArgs.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/ScanProgressEventArgs.cs new file mode 100644 index 000000000..4177ff1b7 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/ScanProgressEventArgs.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public class ScanProgressEventArgs : EventArgs + { + public int CurrentTitle { get; set; } + public int Titles { get; set; } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/AudioCodec.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/AudioCodec.cs new file mode 100644 index 000000000..ee5f8133d --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/AudioCodec.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.SourceData +{ + // Only contains 2 real codecs at the moment as those are what we care about. More will be added later. + public enum AudioCodec + { + Ac3, + + Dts, + + Other + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/AudioTrack.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/AudioTrack.cs new file mode 100644 index 000000000..a7b7926c1 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/AudioTrack.cs @@ -0,0 +1,90 @@ +/* AudioTrack.cs $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.fr>. + It may be used under the terms of the GNU General Public License. */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; + +namespace HandBrake.SourceData +{ + /// <summary> + /// An object represending an AudioTrack associated with a Title, in a DVD + /// </summary> + public class AudioTrack + { + /// <summary> + /// The track number of this Audio Track + /// </summary> + public int TrackNumber { get; set; } + + /// <summary> + /// Gets or sets the audio codec of this Track. + /// </summary> + public AudioCodec Codec { get; set; } + + /// <summary> + /// The language (if detected) of this Audio Track + /// </summary> + public string Language { get; set; } + + public string LanguageCode { get; set; } + + public string Description { get; set; } + + /// <summary> + /// Gets or sets the channel layout of this Audio Track. + /// </summary> + public int ChannelLayout { get; set; } + + /// <summary> + /// The frequency (in Hz) of this Audio Track + /// </summary> + public int SampleRate { get; set; } + + /// <summary> + /// The bitrate (in bits/sec) of this Audio Track. + /// </summary> + public int Bitrate { get; set; } + + public string Display + { + get + { + return this.GetDisplayString(true); + } + } + + public string NoTrackDisplay + { + get + { + return this.GetDisplayString(false); + } + } + + /// <summary> + /// Override of the ToString method to make this object easier to use in the UI + /// </summary> + /// <returns>A string formatted as: {track #} {language} ({format}) ({sub-format})</returns> + public override string ToString() + { + return this.GetDisplayString(true); + } + + private string GetDisplayString(bool includeTrackNumber) + { + if (includeTrackNumber) + { + return this.TrackNumber + " " + this.Description; + } + else + { + return this.Description; + } + } + } +} \ No newline at end of file diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/Chapter.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/Chapter.cs new file mode 100644 index 000000000..74d3703e0 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/Chapter.cs @@ -0,0 +1,38 @@ +/* Chapter.cs $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.fr>. + It may be used under the terms of the GNU General Public License. */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; + +namespace HandBrake.SourceData +{ + /// <summary> + /// An object representing a Chapter aosciated with a Title, in a DVD + /// </summary> + public class Chapter + { + /// <summary> + /// The number of this Chapter, in regards to its parent Title + /// </summary> + public int ChapterNumber { get; set; } + + /// <summary> + /// The length in time this Chapter spans + /// </summary> + public TimeSpan Duration { get; set; } + + /// <summary> + /// Override of the ToString method to make this object easier to use in the UI + /// </summary> + /// <returns>A string formatted as: {chapter #}</returns> + public override string ToString() + { + return this.ChapterNumber.ToString(); + } + } +} \ No newline at end of file diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/InputType.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/InputType.cs new file mode 100644 index 000000000..b96b4f174 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/InputType.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.ComponentModel.DataAnnotations; + +namespace HandBrake.SourceData +{ + public enum InputType + { + [Display(Name = "File")] + Stream, + + [Display(Name = "DVD")] + Dvd, + + [Display(Name = "Blu-ray")] + Bluray + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/Subtitle.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/Subtitle.cs new file mode 100644 index 000000000..5f100db30 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/Subtitle.cs @@ -0,0 +1,54 @@ +/* Subtitle.cs $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.fr>. + It may be used under the terms of the GNU General Public License. */ + +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; + +namespace HandBrake.SourceData +{ + /// <summary> + /// An object that represents a subtitle associated with a Title, in a DVD + /// </summary> + public class Subtitle + { + /// <summary> + /// The track number of this Subtitle + /// </summary> + public int TrackNumber { get; set; } + + /// <summary> + /// The language (if detected) of this Subtitle + /// </summary> + public string Language { get; set; } + + /// <summary> + /// Langauage Code + /// </summary> + public string LanguageCode { get; set; } + + public SubtitleType SubtitleType { get; set; } + + public SubtitleSource SubtitleSource { get; set; } + + /// <summary> + /// Override of the ToString method to make this object easier to use in the UI + /// </summary> + /// <returns>A string formatted as: {track #} {language}</returns> + public override string ToString() + { + return string.Format("{0} {1} ({2})", this.TrackNumber, this.Language, this.SubtitleSource); + } + + public string Display + { + get + { + return this.ToString(); + } + } + } +} \ No newline at end of file diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/SubtitleSource.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/SubtitleSource.cs new file mode 100644 index 000000000..b884b8a32 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/SubtitleSource.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.SourceData +{ + public enum SubtitleSource + { + VobSub, + SRT, + CC608, + CC708, + UTF8, + TX3G, + SSA + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/SubtitleType.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/SubtitleType.cs new file mode 100644 index 000000000..2c4471e99 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/SubtitleType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.SourceData +{ + public enum SubtitleType + { + Picture, + Text + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/Title.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/Title.cs new file mode 100644 index 000000000..c8b296825 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/Title.cs @@ -0,0 +1,144 @@ +/* Title.cs $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.fr>. + It may be used under the terms of the GNU General Public License. */ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text.RegularExpressions; +using HandBrake.Interop; + +namespace HandBrake.SourceData +{ + /// <summary> + /// An object that represents a single Title of a DVD + /// </summary> + public class Title + { + private static readonly CultureInfo Culture = new CultureInfo("en-US", false); + private readonly List<AudioTrack> audioTracks; + private readonly List<Chapter> chapters; + private readonly List<Subtitle> subtitles; + + /// <summary> + /// The constructor for this object + /// </summary> + public Title() + { + this.audioTracks = new List<AudioTrack>(); + this.chapters = new List<Chapter>(); + this.subtitles = new List<Subtitle>(); + } + + /// <summary> + /// Gets or sets the input type of this title. + /// </summary> + public InputType InputType { get; set; } + + /// <summary> + /// Collection of chapters in this Title + /// </summary> + public List<Chapter> Chapters + { + get { return this.chapters; } + } + + /// <summary> + /// Collection of audio tracks associated with this Title + /// </summary> + public List<AudioTrack> AudioTracks + { + get { return this.audioTracks; } + } + + /// <summary> + /// Collection of subtitles associated with this Title + /// </summary> + public List<Subtitle> Subtitles + { + get { return this.subtitles; } + } + + /// <summary> + /// The track number of this Title (1-based). + /// </summary> + public int TitleNumber { get; set; } + + /// <summary> + /// The length in time of this Title + /// </summary> + public TimeSpan Duration { get; set; } + + /// <summary> + /// The resolution (width/height) of this Title + /// </summary> + public Size Resolution { get; set; } + + /// <summary> + /// The aspect ratio of this Title + /// </summary> + public double AspectRatio { get; set; } + + /// <summary> + /// Gets or sets the number of angles on the title. + /// </summary> + public int AngleCount { get; set; } + + /// <summary> + /// Par Value + /// </summary> + public Size ParVal { get; set; } + + /// <summary> + /// The automatically detected crop region for this Title. + /// This is an int array with 4 items in it as so: + /// 0: + /// 1: + /// 2: + /// 3: + /// </summary> + public Cropping AutoCropDimensions { get; set; } + + /// <summary> + /// Gets or sets the name of the video codec for this title. + /// </summary> + public string VideoCodecName { get; set; } + + /// <summary> + /// Gets or sets the video frame rate for this title. + /// </summary> + public double Framerate { get; set; } + + /// <summary> + /// The total number of frames in this title. + /// </summary> + public int Frames + { + get + { + return (int)Math.Ceiling(((double)this.Duration.TotalSeconds) * this.Framerate); + } + } + + /// <summary> + /// Override of the ToString method to provide an easy way to use this object in the UI + /// </summary> + /// <returns>A string representing this track in the format: {title #} (00:00:00)</returns> + public override string ToString() + { + return string.Format("{0} ({1:00}:{2:00}:{3:00})", this.TitleNumber, this.Duration.Hours, + this.Duration.Minutes, this.Duration.Seconds); + } + + public string Display + { + get + { + return this.ToString(); + } + } + } +} \ No newline at end of file diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Utilities.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Utilities.cs new file mode 100644 index 000000000..41ab39da5 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Utilities.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HandBrake.Interop +{ + public static class Utilities + { + public static int GreatestCommonFactor(int a, int b) + { + if (a == 0) + { + return b; + } + + if (b == 0) + { + return a; + } + + if (a > b) + { + return GreatestCommonFactor(a % b, b); + } + else + { + return GreatestCommonFactor(a, b % a); + } + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/libgcc_s_sjlj-1.dll b/win/CS/HandBrake.Interop/HandBrakeInterop/libgcc_s_sjlj-1.dll new file mode 100644 index 000000000..b86e5dfe9 Binary files /dev/null and b/win/CS/HandBrake.Interop/HandBrakeInterop/libgcc_s_sjlj-1.dll differ diff --git a/win/CS/HandBrake.Interop/Local.testsettings b/win/CS/HandBrake.Interop/Local.testsettings new file mode 100644 index 000000000..a371a9d4a --- /dev/null +++ b/win/CS/HandBrake.Interop/Local.testsettings @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<TestSettings name="Local" id="5e2e1c3b-c045-4781-88b7-8fd6b6c6596b" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010"> + <Description>These are default test settings for a local test run.</Description> + <Deployment> + <DeploymentItem filename="..\Lib\x64\hb.dll" /> + <DeploymentItem filename="HandBrakeInterop.Test\TestFiles\Videos\" /> + <DeploymentItem filename="HandBrakeInterop.Test\TestFiles\Jobs\" /> + </Deployment> + <Execution hostProcessPlatform="MSIL"> + <TestTypeSpecific> + <UnitTestRunConfig testTypeId="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b"> + <AssemblyResolution> + <TestDirectory useLoadContext="true" /> + </AssemblyResolution> + </UnitTestRunConfig> + </TestTypeSpecific> + <AgentRule name="LocalMachineDefaultRole"> + </AgentRule> + </Execution> +</TestSettings> \ No newline at end of file diff --git a/win/CS/HandBrake10.sln b/win/CS/HandBrake10.sln index f6a702238..d850cd4da 100644 --- a/win/CS/HandBrake10.sln +++ b/win/CS/HandBrake10.sln @@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandBrake.ApplicationServic EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandBrakeWPF", "HandBrakeWPF\HandBrakeWPF.csproj", "{DADE66CB-0E12-4959-ADE5-0ACD31D27C59}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandBrakeInterop", "HandBrake.Interop\HandBrakeInterop\HandBrakeInterop.csproj", "{F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -103,6 +105,32 @@ Global {DADE66CB-0E12-4959-ADE5-0ACD31D27C59}.Release|x64.ActiveCfg = Release|x86 {DADE66CB-0E12-4959-ADE5-0ACD31D27C59}.Release|x86.ActiveCfg = Release|x86 {DADE66CB-0E12-4959-ADE5-0ACD31D27C59}.Release|x86.Build.0 = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|Any CPU.ActiveCfg = Debug|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|x64.ActiveCfg = Debug|x64 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|x64.Build.0 = Debug|x64 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|x86.ActiveCfg = Debug|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Debug|x86.Build.0 = Debug|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Install|Any CPU.ActiveCfg = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Install|Mixed Platforms.ActiveCfg = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Install|Mixed Platforms.Build.0 = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Install|x64.ActiveCfg = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Install|x86.ActiveCfg = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Install|x86.Build.0 = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.NightlyBuild|Any CPU.ActiveCfg = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.NightlyBuild|Mixed Platforms.ActiveCfg = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.NightlyBuild|Mixed Platforms.Build.0 = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.NightlyBuild|x64.ActiveCfg = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.NightlyBuild|x86.ActiveCfg = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.NightlyBuild|x86.Build.0 = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|Any CPU.ActiveCfg = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|Mixed Platforms.Build.0 = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|x64.ActiveCfg = Release|x64 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|x64.Build.0 = Release|x64 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|x86.ActiveCfg = Release|x86 + {F0A61F62-2C3B-4A87-AFF4-0C4256253DA1}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE -- cgit v1.2.3