From 8b8ebd1f417c6ef65ab431a36fad0bbf0e2daf58 Mon Sep 17 00:00:00 2001 From: sr55 Date: Sun, 30 Oct 2011 17:58:53 +0000 Subject: Interop: Updates to the Interop Library to use the new methods to get at the Audio/Video encoder information from libhb. Patch by RandomEngy. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4329 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- .../Functions/InteropModelCreator.cs | 10 +- .../HandBrakeInterop.Test/TestEncodes.cs | 14 +- .../HandBrakeInterop/Converters.cs | 100 ++++++- .../HandBrakeInterop/HandBrakeInstance.cs | 301 +++++++++++---------- .../HandBrakeInterop/HandBrakeInterop.csproj | 50 ++-- .../HandBrakeInterop/HandBrakeUtils.cs | 198 ++++++-------- .../HandBrakeInterop/HbLib/HbFunctions.cs | 62 ++++- .../HandBrakeInterop/HbLib/Misc.cs | 52 ++-- .../HandBrakeInterop/HbLib/NativeConstants.cs | 5 +- .../HandBrakeInterop/HbLib/hb_audio.cs | 10 +- .../HandBrakeInterop/HbLib/hb_title_s.cs | 2 + .../HandBrakeInterop/InteropUtilities.cs | 49 +++- .../HandBrakeInterop/MarshalingConstants.cs | 36 +-- .../HandBrakeInterop/Model/BitrateLimits.cs | 15 + .../HandBrakeInterop/Model/Encoders.cs | 268 ++++++++++++++++++ .../HandBrakeInterop/Model/Encoding/Anamorphic.cs | 4 +- .../Model/Encoding/AudioEncodeRateType.cs | 19 ++ .../Model/Encoding/AudioEncoder.cs | 3 - .../Model/Encoding/AudioEncoding.cs | 28 +- .../HandBrakeInterop/Model/Encoding/Container.cs | 22 ++ .../Model/Encoding/EncodingProfile.cs | 6 +- .../Model/Encoding/HBAudioEncoder.cs | 53 ++++ .../HandBrakeInterop/Model/Encoding/HBMixdown.cs | 22 ++ .../Model/Encoding/HBVideoEncoder.cs | 19 ++ .../Model/Encoding/VideoEncoder.cs | 11 +- .../HandBrakeInterop/Model/RangeLimits.cs | 16 ++ .../HandBrakeInterop/Properties/AssemblyInfo.cs | 10 +- .../HandBrakeInterop/Settings.StyleCop | 47 +--- .../HandBrakeInterop/SourceData/AudioTrack.cs | 5 + 29 files changed, 1020 insertions(+), 417 deletions(-) create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/BitrateLimits.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoders.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/AudioEncodeRateType.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/Container.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/HBAudioEncoder.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/HBMixdown.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/Encoding/HBVideoEncoder.cs create mode 100644 win/CS/HandBrake.Interop/HandBrakeInterop/Model/RangeLimits.cs (limited to 'win/CS') diff --git a/win/CS/HandBrake.ApplicationServices/Functions/InteropModelCreator.cs b/win/CS/HandBrake.ApplicationServices/Functions/InteropModelCreator.cs index 6221b5784..47d68feab 100644 --- a/win/CS/HandBrake.ApplicationServices/Functions/InteropModelCreator.cs +++ b/win/CS/HandBrake.ApplicationServices/Functions/InteropModelCreator.cs @@ -65,9 +65,9 @@ namespace HandBrake.ApplicationServices.Functions Bitrate = track.Bitrate, Drc = track.DRC, Gain = track.Gain, - Encoder = track.Encoder, + Encoder = Converters.GetCliAudioEncoder(track.Encoder), InputNumber = track.Track.HasValue ? track.Track.Value : 0, - Mixdown = track.MixDown, + Mixdown = Converters.GetCliMixDown(track.MixDown), SampleRateRaw = GetSampleRateRaw(track.SampleRate), }; @@ -113,10 +113,10 @@ namespace HandBrake.ApplicationServices.Functions { case OutputFormat.Mp4: case OutputFormat.M4V: - profile.OutputFormat = Interop.Model.Encoding.OutputFormat.Mp4; + profile.OutputFormat = Container.Mp4; break; case OutputFormat.Mkv: - profile.OutputFormat = Interop.Model.Encoding.OutputFormat.Mkv; + profile.OutputFormat = Container.Mkv; break; } profile.PeakFramerate = work.FramerateMode == FramerateMode.PFR; @@ -136,7 +136,7 @@ namespace HandBrake.ApplicationServices.Functions profile.UseDisplayWidth = true; profile.VideoBitrate = work.VideoBitrate.HasValue ? work.VideoBitrate.Value : 0; profile.VideoEncodeRateType = work.VideoEncodeRateType; - profile.VideoEncoder = work.VideoEncoder; + profile.VideoEncoder = Converters.GetVideoEncoder(work.VideoEncoder); profile.Width = work.Width.HasValue ? work.Width.Value : 0; profile.X264Options = work.AdvancedEncoderOptions; 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 @@ // // // Defines the Converters type. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace HandBrake.Interop -{ - using System; +// +// -------------------------------------------------------------------------------------------------------------------- + +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; + } + } + + /// + /// Converts a native HB encoder structure to an Encoder model. + /// + /// The structure to convert. + /// The converted model. + 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; + } + + /// + /// Converts a native HB encoder structure to an Encoder model. + /// + /// The structure to convert. + /// The converted model. + 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; + } + + /// + /// Converts a native HB mixdown structure to a Mixdown model. + /// + /// The structure to convert. + /// The converted model. + 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 @@ -101,6 +101,14 @@ namespace HandBrake.Interop /// private List encodeAllocatedMemory; + /// + /// Finalizes an instance of the HandBrakeInstance class. + /// + ~HandBrakeInstance() + { + this.Dispose(false); + } + /// /// Fires for progress updates when scanning. /// @@ -121,14 +129,6 @@ namespace HandBrake.Interop /// public event EventHandler EncodeCompleted; - /// - /// Finalizes an instance of the HandBrakeInstance class. - /// - ~HandBrakeInstance() - { - this.Dispose(false); - } - /// /// Gets the list of titles on this instance. /// @@ -162,6 +162,14 @@ namespace HandBrake.Interop } } + /// + /// Call before app shutdown. Performs global cleanup. + /// + public static void DisposeGlobal() + { + HBFunctions.hb_global_close(); + } + /// /// Initializes this instance. /// @@ -600,14 +608,6 @@ namespace HandBrake.Interop GC.SuppressFinalize(this); } - /// - /// Call before app shutdown. Performs global cleanup. - /// - public static void DisposeGlobal() - { - HBFunctions.hb_global_close(); - } - /// /// Frees any resources associated with this object. /// @@ -626,6 +626,100 @@ namespace HandBrake.Interop Marshal.FreeHGlobal(handlePtr); } + /// + /// Calculates the output size for a non-anamorphic job. + /// + /// The encoding profile for the job. + /// The title being encoded. + /// The dimensions of the final encode. + 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); + } + + /// + /// Gets the closest value to the given number divisible by the given modulus. + /// + /// The number to approximate. + /// The modulus. + /// The closest value to the given number divisible by the given modulus. + private static int GetNearestValue(int number, int modulus) + { + return modulus * ((number + modulus / 2) / modulus); + } + /// /// Checks the status of the ongoing scan. /// @@ -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> 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 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(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 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; } - - /// - /// Calculates the output size for a non-anamorphic job. - /// - /// The encoding profile for the job. - /// The title being encoded. - /// The dimensions of the final encode. - 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); - } - - /// - /// Gets the closest value to the given number divisible by the given modulus. - /// - /// The number to approximate. - /// The modulus. - /// The closest value to the given number divisible by the given modulus. - 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 @@ - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + 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 @@ // // // Defines the HandBrakeUtils type. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace HandBrake.Interop -{ - using System; +// +// -------------------------------------------------------------------------------------------------------------------- + +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); } - } - - /// - /// Gets the default mixdown for the given audio encoder and channel layout. - /// - /// The output codec to be used. - /// The input channel layout. - /// The default mixdown for the given codec and channel layout. - public static Mixdown GetDefaultMixdown(AudioEncoder encoder, int layout) - { - int defaultMixdown = HBFunctions.hb_get_default_mixdown(Converters.AudioEncoderToNative(encoder), layout); - return Converters.NativeToMixdown(defaultMixdown); - } - - /// - /// Gets the bitrate limits for the given audio codec, sample rate and mixdown. - /// - /// The audio encoder used. - /// The sample rate used (Hz). - /// The mixdown used. - /// Limits on the audio bitrate for the given settings. - 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 }; - } - - /// - /// Sanitizes a mixdown given the output codec and input channel layout. - /// - /// The desired mixdown. - /// The output encoder to be used. - /// The input channel layout. - /// A sanitized mixdown value. - 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); - } - - /// - /// Sanitizes an audio bitrate given the output codec, sample rate and mixdown. - /// - /// The desired audio bitrate. - /// The output encoder to be used. - /// The output sample rate to be used. - /// The mixdown to be used. - /// A sanitized audio bitrate. - 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)); - } - - /// - /// Gets the total number of seconds on the given encode job. - /// - /// The encode job to query. + } + + /// + /// Gets the total number of seconds on the given encode job. + /// + /// The encode job to query. /// The title being encoded. /// The total number of seconds of video to encode. internal static double GetJobLengthSeconds(EncodeJob job, Title title) @@ -200,37 +142,37 @@ namespace HandBrake.Interop return 0; } - /// - /// Gets the number of audio samples used per frame for the given audio encoder. - /// - /// The encoder to query. - /// The number of audio samples used per frame for the given - /// audio encoder. - 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; - } - - /// + /// + /// Gets the number of audio samples used per frame for the given audio encoder. + /// + /// The encoder to query. + /// The number of audio samples used per frame for the given + /// audio encoder. + 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; + } + + /// /// Gets the size in bytes for the audio with the given parameters. /// /// The encode job. @@ -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 { @@ -191,25 +224,6 @@ namespace HandBrake.Interop.HbLib 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 { 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; - - /// - /// Helper utilities for native interop. - /// - public static class InteropUtilities + + using HandBrake.Interop.HbLib; + + /// + /// Helper utilities for native interop. + /// + public static class InteropUtilities { /// /// Reads the given native structure pointer. @@ -49,12 +49,35 @@ namespace HandBrake.Interop } return returnList; - } - - /// - /// Creats a new, empty native HandBrake list. - /// - /// The capacity of the new list. + } + + /// + /// Converts the given native array to a managed collection. + /// + /// The type of item in the list. + /// The pointer to the array. + /// The number of items in the array. + /// The converted collection. + public static IEnumerable ConvertArray(IntPtr arrayPtr, int count) + { + IntPtr currentItem = arrayPtr; + + var result = new List(); + for (int i = 0; i < count; i++) + { + T nativeEncoder = ReadStructure(currentItem); + result.Add(nativeEncoder); + + currentItem = IntPtr.Add(currentItem, Marshal.SizeOf(typeof(T))); + } + + return result; + } + + /// + /// Creats a new, empty native HandBrake list. + /// + /// The capacity of the new list. /// The new native list. 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 - /// - /// Job Padding Bytes - /// - public const int JobPaddingBytes = 24640; - - /// - /// Audio Padding Bytes - /// - public const int AudioPaddingBytes = 24604; -#endif - } -} + public static class MarshalingConstants + { +#if X64 + public const int JobPaddingBytes = 49264; + public const int AudioPaddingBytes = 49208; +#else + /// + /// Job Padding Bytes + /// + public const int JobPaddingBytes = 49216; + + /// + /// Audio Padding Bytes + /// + 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 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// -------------------------------------------------------------------------------------------------------------------- + +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 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// -------------------------------------------------------------------------------------------------------------------- + +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 audioEncoders; + private static List videoEncoders; + private static List mixdowns; + private static List audioBitrates; + + /// + /// Gets a list of supported audio encoders. + /// + public static List AudioEncoders + { + get + { + if (audioEncoders == null) + { + IntPtr encodersPtr = HBFunctions.hb_get_audio_encoders(); + int encoderCount = HBFunctions.hb_get_audio_encoders_count(); + + audioEncoders = InteropUtilities.ConvertArray(encodersPtr, encoderCount) + .Select(Converters.NativeToAudioEncoder) + .ToList(); + } + + return audioEncoders; + } + } + + /// + /// Gets a list of supported video encoders. + /// + public static List VideoEncoders + { + get + { + if (videoEncoders == null) + { + IntPtr encodersPtr = HBFunctions.hb_get_video_encoders(); + int encoderCount = HBFunctions.hb_get_video_encoders_count(); + + videoEncoders = InteropUtilities.ConvertArray(encodersPtr, encoderCount) + .Select(Converters.NativeToVideoEncoder) + .ToList(); + } + + return videoEncoders; + } + } + + /// + /// Gets a list of supported mixdowns. + /// + public static List Mixdowns + { + get + { + if (mixdowns == null) + { + IntPtr mixdownsPtr = HBFunctions.hb_get_audio_mixdowns(); + int mixdownsCount = HBFunctions.hb_get_audio_mixdowns_count(); + + mixdowns = InteropUtilities.ConvertArray(mixdownsPtr, mixdownsCount) + .Select(Converters.NativeToMixdown) + .ToList(); + } + + return mixdowns; + } + } + + /// + /// Gets a list of supported audio bitrates. + /// + public static List AudioBitrates + { + get + { + if (audioBitrates == null) + { + IntPtr audioBitratesPtr = HBFunctions.hb_get_audio_bitrates(); + int audioBitratesCount = HBFunctions.hb_get_audio_bitrates_count(); + + audioBitrates = InteropUtilities.ConvertArray(audioBitratesPtr, audioBitratesCount) + .Select(b => b.rate) + .ToList(); + } + + return audioBitrates; + } + } + + /// + /// Gets the audio encoder with the specified short name. + /// + /// The name of the audio encoder. + /// The requested audio encoder. + public static HBAudioEncoder GetAudioEncoder(string shortName) + { + return AudioEncoders.SingleOrDefault(e => e.ShortName == shortName); + } + + /// + /// Gets the mixdown with the specified short name. + /// + /// The name of the mixdown. + /// The requested mixdown. + public static HBMixdown GetMixdown(string shortName) + { + return Mixdowns.SingleOrDefault(m => m.ShortName == shortName); + } + + /// + /// Determines if the given encoder is compatible with the given track. + /// + /// The audio track to examine. + /// The encoder to examine. + /// True if the given encoder is comatible with the given audio track. + /// Only works with passthrough encoders. + public static bool AudioEncoderIsCompatible(AudioTrack track, HBAudioEncoder encoder) + { + return (track.CodecId & encoder.Id) > 0; + } + + /// + /// Finds the highest possible mixdown for a given audio encoder. + /// + /// The audio encoder in question. + /// The highest possible mixdown for that audio encoder. + 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; + } + + /// + /// Sanitizes a mixdown given the output codec and input channel layout. + /// + /// The desired mixdown. + /// The output encoder to be used. + /// The input channel layout. + /// A sanitized mixdown value. + 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); + } + + /// + /// Gets the default mixdown for the given audio encoder and channel layout. + /// + /// The output codec to be used. + /// The input channel layout. + /// The default mixdown for the given codec and channel layout. + 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); + } + + /// + /// Gets the bitrate limits for the given audio codec, sample rate and mixdown. + /// + /// The audio encoder used. + /// The sample rate used (Hz). + /// The mixdown used. + /// Limits on the audio bitrate for the given settings. + 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 }; + } + + /// + /// Sanitizes an audio bitrate given the output codec, sample rate and mixdown. + /// + /// The desired audio bitrate. + /// The output encoder to be used. + /// The output sample rate to be used. + /// The mixdown to be used. + /// A sanitized audio bitrate. + 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); + } + + /// + /// Gets the default audio bitrate for the given parameters. + /// + /// The encoder to use. + /// The sample rate to use. + /// The mixdown to use. + /// The default bitrate for these parameters. + public static int GetDefaultBitrate(HBAudioEncoder encoder, int sampleRate, HBMixdown mixdown) + { + return HBFunctions.hb_get_default_audio_bitrate((uint) encoder.Id, sampleRate, mixdown.Id); + } + + /// + /// Gets limits on audio quality for a given encoder. + /// + /// The audio encoder ID. + /// Limits on the audio quality for the given encoder. + 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 + }; + } + + /// + /// Gets limits on audio compression for a given encoder. + /// + /// The audio encoder ID. + /// Limits on the audio compression for the given encoder. + 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 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// -------------------------------------------------------------------------------------------------------------------- + +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 @@ // // This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. // -// -// Defines the AudioEncoder type. -// // -------------------------------------------------------------------------------------------------------------------- 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 @@ -16,6 +16,15 @@ namespace HandBrake.Interop.Model.Encoding /// public class AudioEncoding { + /// + /// Initializes a new instance of the AudioEncoding class. + /// + public AudioEncoding() + { + // Initialize to -1 to differentiate a compression of 0 from uninitialized. + this.Compression = -1; + } + /// /// Gets or sets the chosen track to apply the encoding to. /// @@ -25,17 +34,32 @@ namespace HandBrake.Interop.Model.Encoding /// /// Gets or sets the encoder to use. /// - public AudioEncoder Encoder { get; set; } + public string Encoder { get; set; } + + /// + /// Gets or sets the encode rate type (bitrate or quality). + /// + public AudioEncodeRateType EncodeRateType { get; set; } /// /// Gets or sets the bitrate (in kbps) of this track. /// public int Bitrate { get; set; } + /// + /// Gets or sets the target audio quality for this track. + /// + public float Quality { get; set; } + + /// + /// Gets or sets the target audio compression for this track. + /// + public float Compression { get; set; } + /// /// Gets or sets the mixdown. /// - public Mixdown Mixdown { get; set; } + public string Mixdown { get; set; } /// /// 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 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// -------------------------------------------------------------------------------------------------------------------- + +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 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 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// -------------------------------------------------------------------------------------------------------------------- + +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 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// -------------------------------------------------------------------------------------------------------------------- + +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 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// -------------------------------------------------------------------------------------------------------------------- + +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 @@ // // This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. // -// -// Defines the VideoEncoder type. -// // -------------------------------------------------------------------------------------------------------------------- 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 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// -------------------------------------------------------------------------------------------------------------------- + +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 @@ - - - - - - + + + + + + False - - - - - - - - True - - - - - True - - - - - True - - - - - True - - - - - - - \ No newline at end of file + + + + + 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 @@ -24,6 +24,11 @@ namespace HandBrake.Interop.SourceData /// public AudioCodec Codec { get; set; } + /// + /// Gets or sets the audio codec ID for this track. + /// + public uint CodecId { get; set; } + /// /// Gets or sets the language (if detected) of this Audio Track /// -- cgit v1.2.3