diff options
Diffstat (limited to 'win/CS/HandBrake.Interop')
28 files changed, 1015 insertions, 412 deletions
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop.Test/TestEncodes.cs b/win/CS/HandBrake.Interop/HandBrakeInterop.Test/TestEncodes.cs index 47498ef76..3e625a986 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop.Test/TestEncodes.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop.Test/TestEncodes.cs @@ -51,13 +51,13 @@ namespace HandBrakeInterop.Test 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";
- }
+ } + + string extension; + if (job.EncodingProfile.OutputFormat == Container.Mkv) + { + extension = ".mkv"; + } else
{
extension = ".mp4";
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Converters.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Converters.cs index aeea2a142..9a4b175e5 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/Converters.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Converters.cs @@ -4,12 +4,14 @@ // </copyright>
// <summary>
// Defines the Converters type.
-// </summary>
-// --------------------------------------------------------------------------------------------------------------------
-
-namespace HandBrake.Interop
-{
- using System;
+// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +using HandBrake.Interop.Model; + +namespace HandBrake.Interop +{ + using System; using System.Collections.Generic;
using HandBrake.Interop.HbLib;
@@ -190,8 +192,84 @@ namespace HandBrake.Interop case NativeConstants.HB_ACODEC_CA_HAAC:
return AudioCodec.Aac;
default:
- return AudioCodec.Other;
- }
- }
- }
-}
+ return AudioCodec.Other; + } + } + + /// <summary> + /// Converts a native HB encoder structure to an Encoder model. + /// </summary> + /// <param name="encoder">The structure to convert.</param> + /// <returns>The converted model.</returns> + public static HBVideoEncoder NativeToVideoEncoder(hb_encoder_s encoder) + { + var result = new HBVideoEncoder + { + Id = encoder.encoder, + ShortName = encoder.short_name, + DisplayName = encoder.human_readable_name, + CompatibleContainers = Container.None + }; + + if ((encoder.muxers & NativeConstants.HB_MUX_MKV) > 0) + { + result.CompatibleContainers = result.CompatibleContainers | Container.Mkv; + } + + if ((encoder.muxers & NativeConstants.HB_MUX_MP4) > 0) + { + result.CompatibleContainers = result.CompatibleContainers | Container.Mp4; + } + + return result; + } + + /// <summary> + /// Converts a native HB encoder structure to an Encoder model. + /// </summary> + /// <param name="encoder">The structure to convert.</param> + /// <returns>The converted model.</returns> + public static HBAudioEncoder NativeToAudioEncoder(hb_encoder_s encoder) + { + var result = new HBAudioEncoder + { + Id = encoder.encoder, + ShortName = encoder.short_name, + DisplayName = encoder.human_readable_name, + CompatibleContainers = Container.None + }; + + if ((encoder.muxers & NativeConstants.HB_MUX_MKV) > 0) + { + result.CompatibleContainers = result.CompatibleContainers | Container.Mkv; + } + + if ((encoder.muxers & NativeConstants.HB_MUX_MP4) > 0) + { + result.CompatibleContainers = result.CompatibleContainers | Container.Mp4; + } + + result.QualityLimits = Encoders.GetAudioQualityLimits(encoder.encoder); + result.DefaultQuality = HBFunctions.hb_get_default_audio_quality((uint)encoder.encoder); + result.CompressionLimits = Encoders.GetAudioCompressionLimits(encoder.encoder); + result.DefaultCompression = HBFunctions.hb_get_default_audio_compression((uint) encoder.encoder); + + return result; + } + + /// <summary> + /// Converts a native HB mixdown structure to a Mixdown model. + /// </summary> + /// <param name="mixdown">The structure to convert.</param> + /// <returns>The converted model.</returns> + public static HBMixdown NativeToMixdown(hb_mixdown_s mixdown) + { + return new HBMixdown + { + Id = mixdown.amixdown, + ShortName = mixdown.short_name, + DisplayName = mixdown.human_readable_name + }; + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInstance.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInstance.cs index 71d0bf197..ee3c6e252 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInstance.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInstance.cs @@ -102,6 +102,14 @@ namespace HandBrake.Interop private List<IntPtr> encodeAllocatedMemory;
/// <summary>
+ /// Finalizes an instance of the HandBrakeInstance class.
+ /// </summary>
+ ~HandBrakeInstance()
+ {
+ this.Dispose(false);
+ }
+
+ /// <summary>
/// Fires for progress updates when scanning.
/// </summary>
public event EventHandler<ScanProgressEventArgs> ScanProgress;
@@ -122,14 +130,6 @@ namespace HandBrake.Interop public event EventHandler<EncodeCompletedEventArgs> EncodeCompleted;
/// <summary>
- /// Finalizes an instance of the HandBrakeInstance class.
- /// </summary>
- ~HandBrakeInstance()
- {
- this.Dispose(false);
- }
-
- /// <summary>
/// Gets the list of titles on this instance.
/// </summary>
public List<Title> Titles
@@ -163,6 +163,14 @@ namespace HandBrake.Interop }
/// <summary>
+ /// Call before app shutdown. Performs global cleanup.
+ /// </summary>
+ public static void DisposeGlobal()
+ {
+ HBFunctions.hb_global_close();
+ }
+
+ /// <summary>
/// Initializes this instance.
/// </summary>
/// <param name="verbosity">The code for the logging verbosity to use.</param>
@@ -601,14 +609,6 @@ namespace HandBrake.Interop }
/// <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>
@@ -627,6 +627,100 @@ namespace HandBrake.Interop }
/// <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);
+ }
+
+ /// <summary>
/// Checks the status of the ongoing scan.
/// </summary>
private void PollScanProgress()
@@ -1043,6 +1137,7 @@ namespace HandBrake.Interop nativeJob.anamorphic.par_height = profile.PixelAspectY;
nativeJob.anamorphic.keep_display_aspect = 0;
}
+
break;
default:
break;
@@ -1054,21 +1149,14 @@ namespace HandBrake.Interop nativeJob.maxWidth = profile.MaxWidth;
nativeJob.maxHeight = profile.MaxHeight;
- switch (profile.VideoEncoder)
+ HBVideoEncoder videoEncoder = Encoders.VideoEncoders.FirstOrDefault(e => e.ShortName == profile.VideoEncoder);
+ if (videoEncoder == null)
{
- 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;
+ throw new ArgumentException("Video encoder " + profile.VideoEncoder + " not recognized.");
}
+ nativeJob.vcodec = videoEncoder.Id;
+
if (profile.Framerate == 0)
{
nativeJob.cfr = 0;
@@ -1097,12 +1185,17 @@ namespace HandBrake.Interop int numTracks = 0;
List<Tuple<AudioEncoding, int>> outputTrackList = this.GetOutputTracks(job, title);
- nativeJob.acodec_fallback = (int)Converters.AudioEncoderToNative(profile.AudioEncoderFallback);
+
+ if (profile.AudioEncoderFallback != null)
+ {
+ nativeJob.acodec_fallback = Encoders.GetAudioEncoder(profile.AudioEncoderFallback).Id;
+ }
+
nativeJob.acodec_copy_mask = (int)NativeConstants.HB_ACODEC_ANY;
foreach (Tuple<AudioEncoding, int> outputTrack in outputTrackList)
{
- audioList.Add(ConvertAudioBack(outputTrack.Item1, titleAudio[outputTrack.Item2 - 1], numTracks++, allocatedMemory));
+ audioList.Add(this.ConvertAudioBack(outputTrack.Item1, titleAudio[outputTrack.Item2 - 1], numTracks++, allocatedMemory));
}
NativeList nativeAudioList = InteropUtilities.ConvertListBack<hb_audio_s>(audioList);
@@ -1197,7 +1290,7 @@ namespace HandBrake.Interop }
}
- if (profile.OutputFormat == OutputFormat.Mp4)
+ if (profile.OutputFormat == Container.Mp4)
{
nativeJob.mux = NativeConstants.HB_MUX_MP4;
}
@@ -1339,33 +1432,58 @@ namespace HandBrake.Interop private hb_audio_s ConvertAudioBack(AudioEncoding encoding, hb_audio_s baseStruct, int outputTrack, List<IntPtr> allocatedMemory)
{
hb_audio_s nativeAudio = baseStruct;
+ HBAudioEncoder encoder = Encoders.GetAudioEncoder(encoding.Encoder);
nativeAudio.config.output.track = outputTrack;
- nativeAudio.config.output.codec = Converters.AudioEncoderToNative(encoding.Encoder);
+ nativeAudio.config.output.codec = (uint)encoder.Id;
- if (!Utilities.IsPassthrough(encoding.Encoder))
+ if (!encoder.IsPassthrough)
{
- nativeAudio.config.output.bitrate = encoding.Bitrate;
- nativeAudio.config.output.dynamic_range_compression = encoding.Drc;
- nativeAudio.config.output.gain = encoding.Gain;
-
- if (encoding.Mixdown == Mixdown.Auto)
+ if (encoding.SampleRateRaw == 0)
{
- nativeAudio.config.output.mixdown = HBFunctions.hb_get_default_mixdown(nativeAudio.config.output.codec, nativeAudio.config.input.channel_layout);
+ nativeAudio.config.output.samplerate = nativeAudio.config.input.samplerate;
}
else
{
- nativeAudio.config.output.mixdown = Converters.MixdownToNative(encoding.Mixdown);
+ nativeAudio.config.output.samplerate = encoding.SampleRateRaw;
}
- if (encoding.SampleRateRaw == 0)
+ HBMixdown mixdown = Encoders.GetMixdown(encoding.Mixdown);
+ nativeAudio.config.output.mixdown = mixdown.Id;
+
+ if (encoding.EncodeRateType == AudioEncodeRateType.Bitrate)
{
- nativeAudio.config.output.samplerate = nativeAudio.config.input.samplerate;
+ // Disable quality targeting.
+ nativeAudio.config.output.quality = -1;
+
+ if (encoding.Bitrate == 0)
+ {
+ // Bitrate of 0 means auto: choose the default for this codec, sample rate and mixdown.
+ nativeAudio.config.output.bitrate = HBFunctions.hb_get_default_audio_bitrate(
+ nativeAudio.config.output.codec,
+ nativeAudio.config.output.samplerate,
+ nativeAudio.config.output.mixdown);
+ }
+ else
+ {
+ nativeAudio.config.output.bitrate = encoding.Bitrate;
+ }
}
- else
+ else if (encoding.EncodeRateType == AudioEncodeRateType.Quality)
{
- nativeAudio.config.output.samplerate = encoding.SampleRateRaw;
+ // Bitrate of -1 signals quality targeting.
+ nativeAudio.config.output.bitrate = -1;
+ nativeAudio.config.output.quality = encoding.Quality;
+ }
+
+ // If this encoder supports compression level, pass it in.
+ if (encoder.SupportsCompression)
+ {
+ nativeAudio.config.output.compression_level = encoding.Compression;
}
+
+ nativeAudio.config.output.dynamic_range_compression = encoding.Drc;
+ nativeAudio.config.output.gain = encoding.Gain;
}
if (!string.IsNullOrEmpty(encoding.Name))
@@ -1479,6 +1597,7 @@ namespace HandBrake.Interop {
TrackNumber = currentAudioTrack,
Codec = Converters.NativeToAudioCodec(audio.config.input.codec),
+ CodecId = audio.config.input.codec,
Language = audio.config.lang.simple,
LanguageCode = audio.config.lang.iso639_2,
Description = audio.config.lang.description,
@@ -1506,99 +1625,5 @@ namespace HandBrake.Interop 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 index d877ac1bf..62b901df8 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInterop.csproj +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeInterop.csproj @@ -142,29 +142,35 @@ <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="MessageLoggedEventArgs.cs" /> + <Compile Include="Model\Cropping.cs" /> + <Compile Include="Model\EncodeJob.cs" /> + <Compile Include="Model\Encoders.cs" /> + <Compile Include="Model\Encoding\Anamorphic.cs" /> + <Compile Include="Model\Encoding\AudioEncodeRateType.cs" /> + <Compile Include="Model\Encoding\HBAudioEncoder.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\Encoding\x264\x264Preset.cs" />
- <Compile Include="Model\Encoding\x264\x264Profile.cs" />
- <Compile Include="Model\Encoding\x264\x264Tune.cs" />
- <Compile Include="Model\Limits.cs" />
- <Compile Include="Model\Size.cs" />
- <Compile Include="Model\SourceSubtitle.cs" />
- <Compile Include="Model\SourceType.cs" />
+ <Compile Include="Model\Encoding\Denoise.cs" /> + <Compile Include="Model\Encoding\Detelecine.cs" /> + <Compile Include="Model\Encoding\EncodingProfile.cs" /> + <Compile Include="Model\Encoding\HBMixdown.cs" /> + <Compile Include="Model\Encoding\HBVideoEncoder.cs" /> + <Compile Include="Model\Encoding\Mixdown.cs" /> + <Compile Include="Model\Encoding\OutputExtension.cs" /> + <Compile Include="Model\Encoding\Container.cs" /> + <Compile Include="Model\Encoding\VideoEncoder.cs" /> + <Compile Include="Model\Encoding\VideoEncodeRateType.cs" /> + <Compile Include="Model\Encoding\x264\x264Preset.cs" /> + <Compile Include="Model\Encoding\x264\x264Profile.cs" /> + <Compile Include="Model\Encoding\x264\x264Tune.cs" /> + <Compile Include="Model\BitrateLimits.cs" /> + <Compile Include="Model\RangeLimits.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" />
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeUtils.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeUtils.cs index 4c358da69..908afe250 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeUtils.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HandBrakeUtils.cs @@ -4,12 +4,14 @@ // </copyright>
// <summary>
// Defines the HandBrakeUtils type.
-// </summary>
-// --------------------------------------------------------------------------------------------------------------------
-
-namespace HandBrake.Interop
-{
- using System;
+// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +using System.Runtime.InteropServices; + +namespace HandBrake.Interop +{ + using System; using System.Collections.Generic;
using HandBrake.Interop.HbLib;
@@ -111,72 +113,12 @@ namespace HandBrake.Interop 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>
+ } + + /// <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)
@@ -200,37 +142,37 @@ namespace HandBrake.Interop 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.ffaac:
- case AudioEncoder.AacPassthru:
- case AudioEncoder.Vorbis:
- return 1024;
- case AudioEncoder.Lame:
- case AudioEncoder.Mp3Passthru:
- return 1152;
- case AudioEncoder.Ac3:
- case AudioEncoder.Passthrough:
- case AudioEncoder.Ac3Passthrough:
- case AudioEncoder.DtsPassthrough:
- case AudioEncoder.DtsHDPassthrough:
- return 1536;
- }
-
- System.Diagnostics.Debug.Assert(true, "Audio encoder unrecognized.");
- return 0;
- }
-
- /// <summary>
+ /// <summary> + /// Gets the number of audio samples used per frame for the given audio encoder. + /// </summary> + /// <param name="encoderName">The encoder to query.</param> + /// <returns>The number of audio samples used per frame for the given + /// audio encoder.</returns> + internal static int GetAudioSamplesPerFrame(string encoderName) + { + switch (encoderName) + { + case "faac": + case "ffaac": + case "copy:aac": + case "vorbis": + return 1024; + case "lame": + case "copy:mp3": + return 1152; + case "ffac3": + case "copy": + case "copy:ac3": + case "copy:dts": + case "copy:dtshd": + return 1536; + } + + // Unknown encoder; make a guess. + return 1536; + } + + /// <summary> /// Gets the size in bytes for the audio with the given parameters.
/// </summary>
/// <param name="job">The encode job.</param>
@@ -247,21 +189,41 @@ namespace HandBrake.Interop AudioEncoding encoding = outputTrack.Item1;
AudioTrack track = title.AudioTracks[outputTrack.Item2 - 1];
- int samplesPerFrame = HandBrakeUtils.GetAudioSamplesPerFrame(encoding.Encoder);
- int audioBitrate;
-
- if (Utilities.IsPassthrough(encoding.Encoder))
- {
- // 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);
+ int samplesPerFrame = HandBrakeUtils.GetAudioSamplesPerFrame(encoding.Encoder); + int audioBitrate; + + HBAudioEncoder audioEncoder = Encoders.GetAudioEncoder(encoding.Encoder); + + if (audioEncoder.IsPassthrough) + { + // Input bitrate is in bits/second. + audioBitrate = track.Bitrate / 8; + } + else if (encoding.EncodeRateType == AudioEncodeRateType.Quality) + { + // Can't predict size of quality targeted audio encoding. + audioBitrate = 0; + } + else + { + int outputBitrate; + if (encoding.Bitrate > 0) + { + outputBitrate = encoding.Bitrate; + } + else + { + outputBitrate = Encoders.GetDefaultBitrate( + audioEncoder, + encoding.SampleRateRaw == 0 ? track.SampleRate : encoding.SampleRateRaw, + Encoders.SanitizeMixdown(Encoders.GetMixdown(encoding.Mixdown), audioEncoder, track.ChannelLayout)); + } + + // Output bitrate is in kbps. + audioBitrate = outputBitrate * 1000 / 8; + } + + audioBytes += (long)(lengthSeconds * audioBitrate); // Audio overhead
audioBytes += encoding.SampleRateRaw * ContainerOverheadPerFrame / samplesPerFrame;
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/HbFunctions.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/HbFunctions.cs index 7e87475cc..7cc7e1b40 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/HbFunctions.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/HbFunctions.cs @@ -10,10 +10,10 @@ namespace HandBrake.Interop.HbLib
{
- using System;
- using System.Runtime.InteropServices;
+ using System;
+ using System.Runtime.InteropServices;
- public static class HBFunctions
+ public static class HBFunctions
{
[DllImport("hb.dll", EntryPoint = "hb_register_logger", CallingConvention = CallingConvention.Cdecl)]
public static extern void hb_register_logger(LoggingCallback callback);
@@ -229,6 +229,7 @@ namespace HandBrake.Interop.HbLib [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);
@@ -238,7 +239,62 @@ namespace HandBrake.Interop.HbLib [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_default_audio_bitrate", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_get_default_audio_bitrate(uint codec, 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);
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_audio_quality_limits", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_get_audio_quality_limits(uint codec, ref float low, ref float high, ref float granularity, ref int direction);
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_default_audio_quality", CallingConvention = CallingConvention.Cdecl)]
+ public static extern float hb_get_default_audio_quality(uint codec);
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_audio_compression_limits", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_get_audio_compression_limits(uint codec, ref float low, ref float high, ref float granularity, ref int direction);
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_default_audio_compression", CallingConvention = CallingConvention.Cdecl)]
+ public static extern float hb_get_default_audio_compression(uint codec);
+
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_video_rates", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_get_video_rates();
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_video_rates_count", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_get_video_rates_count();
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_audio_rates", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_get_audio_rates();
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_audio_rates_count", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_get_audio_rates_count();
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_audio_rates_default", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_get_audio_rates_default();
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_audio_bitrates", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_get_audio_bitrates();
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_audio_bitrates_count", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_get_audio_bitrates_count();
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_audio_mixdowns", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_get_audio_mixdowns();
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_audio_mixdowns_count", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_get_audio_mixdowns_count();
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_video_encoders", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_get_video_encoders();
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_video_encoders_count", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_get_video_encoders_count();
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_audio_encoders", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_get_audio_encoders();
+
+ [DllImport("hb.dll", EntryPoint = "hb_get_audio_encoders_count", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_get_audio_encoders_count();
}
}
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/Misc.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/Misc.cs index cc007596a..753b7edd2 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/Misc.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/Misc.cs @@ -62,6 +62,39 @@ namespace HandBrake.Interop.HbLib public int rate;
}
+ [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_encoder_s
+ {
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string human_readable_name;
+
+ [MarshalAs(UnmanagedType.LPStr)]
+ public string short_name;
+
+ public int encoder;
+
+ public int muxers;
+ }
+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct hb_metadata_s
{
@@ -192,25 +225,6 @@ namespace HandBrake.Interop.HbLib }
[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*
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/NativeConstants.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/NativeConstants.cs index ebbe0766a..aae152dce 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/NativeConstants.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/NativeConstants.cs @@ -12,7 +12,7 @@ namespace HandBrake.Interop.HbLib {
public partial class NativeConstants
{
- public const uint HB_ACODEC_MASK = 0x0000FF00;
+ public const uint HB_ACODEC_MASK = 0x001FFF00;
public const uint HB_ACODEC_FAAC = 0x00000100;
public const uint HB_ACODEC_LAME = 0x00000200;
public const uint HB_ACODEC_VORBIS = 0x00000400;
@@ -25,7 +25,8 @@ namespace HandBrake.Interop.HbLib public const uint HB_ACODEC_FFMPEG = 0x00020000;
public const uint HB_ACODEC_DCA_HD = 0x00040000;
public const uint HB_ACODEC_MP3 = 0x00080000;
- public const uint HB_ACODEC_FF_MASK = 0x000f0000;
+ public const uint HB_ACODEC_FFFLAC = 0x00100000;
+ public const uint HB_ACODEC_FF_MASK = 0x001f0000;
public const uint HB_ACODEC_PASS_FLAG = 0x40000000;
public const uint HB_ACODEC_PASS_MASK = (HB_ACODEC_MP3 | HB_ACODEC_FFAAC | HB_ACODEC_DCA_HD | HB_ACODEC_AC3 | HB_ACODEC_DCA);
public const uint HB_ACODEC_AUTO_PASS = (HB_ACODEC_PASS_MASK | HB_ACODEC_PASS_FLAG);
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_audio.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_audio.cs index 740f1eacf..6decf10d0 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_audio.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_audio.cs @@ -10,10 +10,10 @@ namespace HandBrake.Interop.HbLib
{
- using System;
- using System.Runtime.InteropServices;
+ using System;
+ using System.Runtime.InteropServices;
- [StructLayout(LayoutKind.Sequential)]
+ [StructLayout(LayoutKind.Sequential)]
public struct hb_audio_s
{
/// int
@@ -59,6 +59,10 @@ namespace HandBrake.Interop.HbLib /// int
public int bitrate;
+ public float quality;
+
+ public float compression_level;
+
/// int
public int mixdown;
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_title_s.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_title_s.cs index 117787c1b..bc4e2a7ff 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_title_s.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_title_s.cs @@ -78,6 +78,8 @@ namespace HandBrake.Interop.HbLib /// double
public double container_aspect;
+ public int has_resolution_change;
+
/// int
public int width;
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/InteropUtilities.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/InteropUtilities.cs index 40c2571a9..3a36ddfc9 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/InteropUtilities.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/InteropUtilities.cs @@ -12,13 +12,13 @@ namespace HandBrake.Interop using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
-
- using HandBrake.Interop.HbLib;
-
- /// <summary>
- /// Helper utilities for native interop.
- /// </summary>
- public static class InteropUtilities
+ + using HandBrake.Interop.HbLib; + + /// <summary> + /// Helper utilities for native interop. + /// </summary> + public static class InteropUtilities {
/// <summary>
/// Reads the given native structure pointer.
@@ -49,12 +49,35 @@ namespace HandBrake.Interop }
return returnList;
- }
-
- /// <summary>
- /// Creats a new, empty native HandBrake list.
- /// </summary>
- /// <param name="capacity">The capacity of the new list.</param>
+ } + + /// <summary> + /// Converts the given native array to a managed collection. + /// </summary> + /// <typeparam name="T">The type of item in the list.</typeparam> + /// <param name="arrayPtr">The pointer to the array.</param> + /// <param name="count">The number of items in the array.</param> + /// <returns>The converted collection.</returns> + public static IEnumerable<T> ConvertArray<T>(IntPtr arrayPtr, int count) + { + IntPtr currentItem = arrayPtr; + + var result = new List<T>(); + for (int i = 0; i < count; i++) + { + T nativeEncoder = ReadStructure<T>(currentItem); + result.Add(nativeEncoder); + + currentItem = IntPtr.Add(currentItem, Marshal.SizeOf(typeof(T))); + } + + return result; + } + + /// <summary> + /// Creats a new, empty native HandBrake list. + /// </summary> + /// <param name="capacity">The capacity of the new list.</param> /// <returns>The new native list.</returns>
public static NativeList CreateNativeList(int capacity)
{
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/MarshalingConstants.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/MarshalingConstants.cs index 66dc737fb..07ebc0810 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/MarshalingConstants.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/MarshalingConstants.cs @@ -9,21 +9,21 @@ namespace HandBrake.Interop
{
- public static class MarshalingConstants
- {
-#if X64
- public const int JobPaddingBytes = 24688;
- public const int AudioPaddingBytes = 24632;
-#else
- /// <summary>
- /// Job Padding Bytes
- /// </summary>
- public const int JobPaddingBytes = 24640;
-
- /// <summary>
- /// Audio Padding Bytes
- /// </summary>
- public const int AudioPaddingBytes = 24604;
-#endif
- }
-}
+ public static class MarshalingConstants + { +#if X64 + public const int JobPaddingBytes = 49264; + public const int AudioPaddingBytes = 49208; +#else + /// <summary> + /// Job Padding Bytes + /// </summary> + public const int JobPaddingBytes = 49216; + + /// <summary> + /// Audio Padding Bytes + /// </summary> + public const int AudioPaddingBytes = 49180; +#endif + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/BitrateLimits.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/BitrateLimits.cs new file mode 100644 index 000000000..8e6a49582 --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/BitrateLimits.cs @@ -0,0 +1,15 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="BitrateLimits.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Interop.Model +{ + public class BitrateLimits + { + public int Low { get; set; } + + public int High { get; set; } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoders.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoders.cs new file mode 100644 index 000000000..9857bb6ad --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoders.cs @@ -0,0 +1,268 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="Encoders.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Interop.Model +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Runtime.InteropServices; + using HandBrake.Interop.HbLib; + using HandBrake.Interop.Model.Encoding; + using HandBrake.Interop.SourceData; + + public static class Encoders + { + private static List<HBAudioEncoder> audioEncoders; + private static List<HBVideoEncoder> videoEncoders; + private static List<HBMixdown> mixdowns; + private static List<int> audioBitrates; + + /// <summary> + /// Gets a list of supported audio encoders. + /// </summary> + public static List<HBAudioEncoder> AudioEncoders + { + get + { + if (audioEncoders == null) + { + IntPtr encodersPtr = HBFunctions.hb_get_audio_encoders(); + int encoderCount = HBFunctions.hb_get_audio_encoders_count(); + + audioEncoders = InteropUtilities.ConvertArray<hb_encoder_s>(encodersPtr, encoderCount) + .Select(Converters.NativeToAudioEncoder) + .ToList(); + } + + return audioEncoders; + } + } + + /// <summary> + /// Gets a list of supported video encoders. + /// </summary> + public static List<HBVideoEncoder> VideoEncoders + { + get + { + if (videoEncoders == null) + { + IntPtr encodersPtr = HBFunctions.hb_get_video_encoders(); + int encoderCount = HBFunctions.hb_get_video_encoders_count(); + + videoEncoders = InteropUtilities.ConvertArray<hb_encoder_s>(encodersPtr, encoderCount) + .Select(Converters.NativeToVideoEncoder) + .ToList(); + } + + return videoEncoders; + } + } + + /// <summary> + /// Gets a list of supported mixdowns. + /// </summary> + public static List<HBMixdown> Mixdowns + { + get + { + if (mixdowns == null) + { + IntPtr mixdownsPtr = HBFunctions.hb_get_audio_mixdowns(); + int mixdownsCount = HBFunctions.hb_get_audio_mixdowns_count(); + + mixdowns = InteropUtilities.ConvertArray<hb_mixdown_s>(mixdownsPtr, mixdownsCount) + .Select(Converters.NativeToMixdown) + .ToList(); + } + + return mixdowns; + } + } + + /// <summary> + /// Gets a list of supported audio bitrates. + /// </summary> + public static List<int> AudioBitrates + { + get + { + if (audioBitrates == null) + { + IntPtr audioBitratesPtr = HBFunctions.hb_get_audio_bitrates(); + int audioBitratesCount = HBFunctions.hb_get_audio_bitrates_count(); + + audioBitrates = InteropUtilities.ConvertArray<hb_rate_s>(audioBitratesPtr, audioBitratesCount) + .Select(b => b.rate) + .ToList(); + } + + return audioBitrates; + } + } + + /// <summary> + /// Gets the audio encoder with the specified short name. + /// </summary> + /// <param name="shortName">The name of the audio encoder.</param> + /// <returns>The requested audio encoder.</returns> + public static HBAudioEncoder GetAudioEncoder(string shortName) + { + return AudioEncoders.SingleOrDefault(e => e.ShortName == shortName); + } + + /// <summary> + /// Gets the mixdown with the specified short name. + /// </summary> + /// <param name="shortName">The name of the mixdown.</param> + /// <returns>The requested mixdown.</returns> + public static HBMixdown GetMixdown(string shortName) + { + return Mixdowns.SingleOrDefault(m => m.ShortName == shortName); + } + + /// <summary> + /// Determines if the given encoder is compatible with the given track. + /// </summary> + /// <param name="track">The audio track to examine.</param> + /// <param name="encoder">The encoder to examine.</param> + /// <returns>True if the given encoder is comatible with the given audio track.</returns> + /// <remarks>Only works with passthrough encoders.</remarks> + public static bool AudioEncoderIsCompatible(AudioTrack track, HBAudioEncoder encoder) + { + return (track.CodecId & encoder.Id) > 0; + } + + /// <summary> + /// Finds the highest possible mixdown for a given audio encoder. + /// </summary> + /// <param name="audioEncoder">The audio encoder in question.</param> + /// <returns>The highest possible mixdown for that audio encoder.</returns> + public static int GetMaxMixdownIndex(HBAudioEncoder audioEncoder) + { + // To find best case scenario, pass in highest number of channels and 6 channel discrete mixdown. + int maxMixdownId = HBFunctions.hb_get_best_mixdown((uint)audioEncoder.Id, NativeConstants.HB_INPUT_CH_LAYOUT_3F4R, NativeConstants.HB_AMIXDOWN_6CH); + + for (int i = 0; i < Mixdowns.Count; i++) + { + if (Mixdowns[i].Id == maxMixdownId) + { + return i; + } + } + + return -1; + } + + /// <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 HBMixdown SanitizeMixdown(HBMixdown mixdown, HBAudioEncoder encoder, int layout) + { + int sanitizedMixdown = HBFunctions.hb_get_best_mixdown((uint)encoder.Id, layout, mixdown.Id); + return Mixdowns.Single(m => m.Id == sanitizedMixdown); + } + + /// <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 HBMixdown GetDefaultMixdown(HBAudioEncoder encoder, int layout) + { + int defaultMixdown = HBFunctions.hb_get_default_mixdown((uint)encoder.Id, layout); + return Mixdowns.Single(m => m.Id == 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 BitrateLimits GetBitrateLimits(HBAudioEncoder encoder, int sampleRate, HBMixdown mixdown) + { + int low = 0; + int high = 0; + + HBFunctions.hb_get_audio_bitrate_limits((uint)encoder.Id, sampleRate, mixdown.Id, ref low, ref high); + + return new BitrateLimits { Low = low, High = high }; + } + + /// <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, HBAudioEncoder encoder, int sampleRate, HBMixdown mixdown) + { + return HBFunctions.hb_get_best_audio_bitrate((uint)encoder.Id, audioBitrate, sampleRate, mixdown.Id); + } + + /// <summary> + /// Gets the default audio bitrate for the given parameters. + /// </summary> + /// <param name="encoder">The encoder to use.</param> + /// <param name="sampleRate">The sample rate to use.</param> + /// <param name="mixdown">The mixdown to use.</param> + /// <returns>The default bitrate for these parameters.</returns> + public static int GetDefaultBitrate(HBAudioEncoder encoder, int sampleRate, HBMixdown mixdown) + { + return HBFunctions.hb_get_default_audio_bitrate((uint) encoder.Id, sampleRate, mixdown.Id); + } + + /// <summary> + /// Gets limits on audio quality for a given encoder. + /// </summary> + /// <param name="encoderId">The audio encoder ID.</param> + /// <returns>Limits on the audio quality for the given encoder.</returns> + internal static RangeLimits GetAudioQualityLimits(int encoderId) + { + float low = 0, high = 0, granularity = 0; + int direction = 0; + HBFunctions.hb_get_audio_quality_limits((uint)encoderId, ref low, ref high, ref granularity, ref direction); + + return new RangeLimits + { + Low = low, + High = high, + Granularity = granularity, + Ascending = direction == 0 + }; + } + + /// <summary> + /// Gets limits on audio compression for a given encoder. + /// </summary> + /// <param name="encoderId">The audio encoder ID.</param> + /// <returns>Limits on the audio compression for the given encoder.</returns> + internal static RangeLimits GetAudioCompressionLimits(int encoderId) + { + float low = 0, high = 0, granularity = 0; + int direction = 0; + HBFunctions.hb_get_audio_compression_limits((uint)encoderId, ref low, ref high, ref granularity, ref direction); + + return new RangeLimits + { + Low = low, + High = high, + Granularity = granularity, + Ascending = direction == 0 + }; + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Anamorphic.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Anamorphic.cs index 2051c2b63..2d20c4376 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Anamorphic.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Anamorphic.cs @@ -9,9 +9,9 @@ namespace HandBrake.Interop.Model.Encoding
{
- using System.ComponentModel.DataAnnotations;
+ using System.ComponentModel.DataAnnotations;
- public enum Anamorphic
+ public enum Anamorphic
{
[Display(Name = "None")]
None = 0,
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncodeRateType.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncodeRateType.cs new file mode 100644 index 000000000..ca162a47f --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncodeRateType.cs @@ -0,0 +1,19 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="AudioEncodeRateType.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Interop.Model.Encoding +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + public enum AudioEncodeRateType + { + Bitrate, + Quality + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoder.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoder.cs index b5ab3b4bc..492d51d9a 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoder.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoder.cs @@ -2,9 +2,6 @@ // <copyright file="AudioEncoder.cs" company="HandBrake Project (http://handbrake.fr)">
// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
// </copyright>
-// <summary>
-// Defines the AudioEncoder type.
-// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace HandBrake.Interop.Model.Encoding
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoding.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoding.cs index ea11d182e..c6ac28ea5 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoding.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncoding.cs @@ -17,6 +17,15 @@ namespace HandBrake.Interop.Model.Encoding public class AudioEncoding
{
/// <summary>
+ /// Initializes a new instance of the AudioEncoding class.
+ /// </summary>
+ public AudioEncoding()
+ {
+ // Initialize to -1 to differentiate a compression of 0 from uninitialized.
+ this.Compression = -1;
+ }
+
+ /// <summary>
/// Gets or sets the chosen track to apply the encoding to.
/// </summary>
/// <remarks>1-based index. 0 means apply to all tracks.</remarks>
@@ -25,7 +34,12 @@ namespace HandBrake.Interop.Model.Encoding /// <summary>
/// Gets or sets the encoder to use.
/// </summary>
- public AudioEncoder Encoder { get; set; }
+ public string Encoder { get; set; }
+
+ /// <summary>
+ /// Gets or sets the encode rate type (bitrate or quality).
+ /// </summary>
+ public AudioEncodeRateType EncodeRateType { get; set; }
/// <summary>
/// Gets or sets the bitrate (in kbps) of this track.
@@ -33,9 +47,19 @@ namespace HandBrake.Interop.Model.Encoding public int Bitrate { get; set; }
/// <summary>
+ /// Gets or sets the target audio quality for this track.
+ /// </summary>
+ public float Quality { get; set; }
+
+ /// <summary>
+ /// Gets or sets the target audio compression for this track.
+ /// </summary>
+ public float Compression { get; set; }
+
+ /// <summary>
/// Gets or sets the mixdown.
/// </summary>
- public Mixdown Mixdown { get; set; }
+ public string Mixdown { get; set; }
/// <summary>
/// Gets or sets the sample rate. Obsolete. Use SampleRateRaw instead.
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Container.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Container.cs new file mode 100644 index 000000000..2a526170e --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Container.cs @@ -0,0 +1,22 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="Container.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Interop.Model.Encoding +{ + using System; + using System.ComponentModel.DataAnnotations; + + [Flags] + public enum Container + { + None = 0x0, + + [Display(Name = "MP4")] + Mp4, + [Display(Name = "MKV")] + Mkv + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/EncodingProfile.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/EncodingProfile.cs index d4f85ca81..25da728ef 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/EncodingProfile.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/EncodingProfile.cs @@ -20,7 +20,7 @@ namespace HandBrake.Interop.Model.Encoding this.Cropping = new Cropping();
}
- public OutputFormat OutputFormat { get; set; }
+ public Container OutputFormat { get; set; }
public OutputExtension PreferredExtension { get; set; }
public bool IncludeChapterMarkers { get; set; }
public bool LargeFile { get; set; }
@@ -52,7 +52,7 @@ namespace HandBrake.Interop.Model.Encoding public int Deblock { get; set; }
public bool Grayscale { get; set; }
- public VideoEncoder VideoEncoder { get; set; }
+ public string VideoEncoder { get; set; }
public string X264Options { get; set; }
public string X264Profile { get; set; }
public string X264Preset { get; set; }
@@ -67,7 +67,7 @@ namespace HandBrake.Interop.Model.Encoding public bool PeakFramerate { get; set; }
public List<AudioEncoding> AudioEncodings { get; set; }
- public AudioEncoder AudioEncoderFallback { get; set; }
+ public string AudioEncoderFallback { get; set; }
public EncodingProfile Clone()
{
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/HBAudioEncoder.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/HBAudioEncoder.cs new file mode 100644 index 000000000..19645a70b --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/HBAudioEncoder.cs @@ -0,0 +1,53 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="HBAudioEncoder.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Interop.Model.Encoding +{ + using HandBrake.Interop.HbLib; + + public class HBAudioEncoder + { + public string ShortName { get; set; } + + public string DisplayName { get; set; } + + public int Id { get; set; } + + public Container CompatibleContainers { get; set; } + + public bool SupportsQuality + { + get + { + return this.QualityLimits.High >= 0; + } + } + + public RangeLimits QualityLimits { get; set; } + + public float DefaultQuality { get; set; } + + public bool SupportsCompression + { + get + { + return this.CompressionLimits.High >= 0; + } + } + + public RangeLimits CompressionLimits { get; set; } + + public float DefaultCompression { get; set; } + + public bool IsPassthrough + { + get + { + return (this.Id & NativeConstants.HB_ACODEC_PASS_FLAG) > 0; + } + } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/HBMixdown.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/HBMixdown.cs new file mode 100644 index 000000000..493beb9fa --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/HBMixdown.cs @@ -0,0 +1,22 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="HBMixdown.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Interop.Model.Encoding +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + + public class HBMixdown + { + public string ShortName { get; set; } + + public string DisplayName { get; set; } + + public int Id { get; set; } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/HBVideoEncoder.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/HBVideoEncoder.cs new file mode 100644 index 000000000..9e04252aa --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/HBVideoEncoder.cs @@ -0,0 +1,19 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="HBVideoEncoder.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Interop.Model.Encoding +{ + public class HBVideoEncoder + { + public string ShortName { get; set; } + + public string DisplayName { get; set; } + + public int Id { get; set; } + + public Container CompatibleContainers { get; set; } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/VideoEncoder.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/VideoEncoder.cs index 1e7b8005c..31cc3d599 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/VideoEncoder.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/VideoEncoder.cs @@ -2,16 +2,13 @@ // <copyright file="VideoEncoder.cs" company="HandBrake Project (http://handbrake.fr)">
// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
// </copyright>
-// <summary>
-// Defines the VideoEncoder type.
-// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace HandBrake.Interop.Model.Encoding
{
- using System.ComponentModel.DataAnnotations;
+ using System.ComponentModel.DataAnnotations;
- public enum VideoEncoder
+ public enum VideoEncoder
{
[Display(Name = "H.264 (x264)")]
X264 = 0,
@@ -19,8 +16,8 @@ namespace HandBrake.Interop.Model.Encoding [Display(Name = "MPEG-4 (FFmpeg)")]
FFMpeg,
- [Display(Name = "MPEG-2 (FFmpeg)")]
- FFMpeg2,
+ [Display(Name = "MPEG-2 (FFmpeg)")]
+ FFMpeg2,
[Display(Name = "VP3 (Theora)")]
Theora
diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Model/RangeLimits.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/RangeLimits.cs new file mode 100644 index 000000000..6055e8eed --- /dev/null +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Model/RangeLimits.cs @@ -0,0 +1,16 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="RangeLimits.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Interop.Model +{ + public class RangeLimits + { + public float Low { get; set; } + public float High { get; set; } + public float Granularity { get; set; } + public bool Ascending { get; set; } + } +} diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Properties/AssemblyInfo.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/Properties/AssemblyInfo.cs index 8e87db998..b9f0c721c 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/Properties/AssemblyInfo.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Properties/AssemblyInfo.cs @@ -29,8 +29,8 @@ using System.Runtime.InteropServices; // 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.22.0.0")]
-[assembly: AssemblyFileVersion("1.22.0.0")]
+// 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.23.0.0")] +[assembly: AssemblyFileVersion("1.23.0.0")] diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/Settings.StyleCop b/win/CS/HandBrake.Interop/HandBrakeInterop/Settings.StyleCop index b34002f52..39d8ff868 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/Settings.StyleCop +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/Settings.StyleCop @@ -1,39 +1,14 @@ -<StyleCopSettings Version="105">
- <Analyzers>
- <Analyzer AnalyzerId="StyleCop.CSharp.SpacingRules">
- <Rules>
- <Rule Name="TabsMustNotBeUsed">
- <RuleSettings>
+<StyleCopSettings Version="4.3"> + <Analyzers> + <Analyzer AnalyzerId="Microsoft.StyleCop.CSharp.SpacingRules"> + <Rules> + <Rule Name="TabsMustNotBeUsed"> + <RuleSettings> <BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
- </Rules>
- <AnalyzerSettings />
- </Analyzer>
- <Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
- <Rules>
- <Rule Name="FileMustHaveHeader">
- <RuleSettings>
- <BooleanProperty Name="Enabled">True</BooleanProperty>
- </RuleSettings>
- </Rule>
- <Rule Name="FileHeaderMustShowCopyright">
- <RuleSettings>
- <BooleanProperty Name="Enabled">True</BooleanProperty>
- </RuleSettings>
- </Rule>
- <Rule Name="FileHeaderMustHaveCopyrightText">
- <RuleSettings>
- <BooleanProperty Name="Enabled">True</BooleanProperty>
- </RuleSettings>
- </Rule>
- <Rule Name="FileHeaderMustContainFileName">
- <RuleSettings>
- <BooleanProperty Name="Enabled">True</BooleanProperty>
- </RuleSettings>
- </Rule>
- </Rules>
- <AnalyzerSettings />
- </Analyzer>
- </Analyzers>
-</StyleCopSettings>
\ No newline at end of file + </Rules> + <AnalyzerSettings /> + </Analyzer> + </Analyzers> +</StyleCopSettings> diff --git a/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/AudioTrack.cs b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/AudioTrack.cs index 38d9b344a..bd7ca3ef2 100644 --- a/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/AudioTrack.cs +++ b/win/CS/HandBrake.Interop/HandBrakeInterop/SourceData/AudioTrack.cs @@ -25,6 +25,11 @@ namespace HandBrake.Interop.SourceData public AudioCodec Codec { get; set; }
/// <summary>
+ /// Gets or sets the audio codec ID for this track.
+ /// </summary>
+ public uint CodecId { get; set; }
+
+ /// <summary>
/// Gets or sets the language (if detected) of this Audio Track
/// </summary>
public string Language { get; set; }
|