// -------------------------------------------------------------------------------------------------------------------- // // This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. // // // The encoders. // // -------------------------------------------------------------------------------------------------------------------- namespace HandBrake.Interop.Interop { using System; using System.Collections.Generic; using System.Linq; using HandBrake.Interop.Interop.HbLib; using HandBrake.Interop.Interop.Helpers; using HandBrake.Interop.Interop.Interfaces.Model; using HandBrake.Interop.Interop.Interfaces.Model.Encoders; using HandBrake.Interop.Utilities; public static class HandBrakeEncoderHelpers { private static List audioEncoders; private static List videoEncoders; private static List videoFramerates; private static List mixdowns; private static List containers; private static List audioBitrates; private static List audioSampleRates; /// /// Initializes static members of the HandBrakeEncoderHelpers class. /// static HandBrakeEncoderHelpers() { if (!HandBrakeUtils.IsInitialised()) { throw new Exception("Please Initialise with HandBrakeUtils.EnsureGlobalInit before using!"); } } /// /// Gets a list of supported audio encoders. /// public static List AudioEncoders { get { if (audioEncoders == null) { audioEncoders = InteropUtilities.ToListFromIterator(HBFunctions.hb_audio_encoder_get_next, HandBrakeUnitConversionHelpers.NativeToAudioEncoder); } return audioEncoders; } } /// /// Gets a list of supported video encoders. /// public static List VideoEncoders { get { if (videoEncoders == null) { videoEncoders = InteropUtilities.ToListFromIterator(HBFunctions.hb_video_encoder_get_next, HandBrakeUnitConversionHelpers.NativeToVideoEncoder); } return videoEncoders; } } /// /// Gets a list of supported video framerates (in pts). /// public static List VideoFramerates { get { if (videoFramerates == null) { videoFramerates = InteropUtilities.ToListFromIterator(HBFunctions.hb_video_framerate_get_next, HandBrakeUnitConversionHelpers.NativeToRate); } return videoFramerates; } } /// /// Gets a list of supported mixdowns. /// public static List Mixdowns { get { if (mixdowns == null) { mixdowns = InteropUtilities.ToListFromIterator(HBFunctions.hb_mixdown_get_next, HandBrakeUnitConversionHelpers.NativeToMixdown); } return mixdowns; } } /// /// Gets a list of supported audio bitrates. /// public static List AudioBitrates { get { if (audioBitrates == null) { audioBitrates = InteropUtilities.ToListFromIterator(HBFunctions.hb_audio_bitrate_get_next, b => b.rate); } return audioBitrates; } } /// /// Gets a list of supported audio sample rates (in Hz). /// public static List AudioSampleRates { get { if (audioSampleRates == null) { audioSampleRates = InteropUtilities.ToListFromIterator(HBFunctions.hb_audio_samplerate_get_next, HandBrakeUnitConversionHelpers.NativeToRate); } return audioSampleRates; } } /// /// Gets a list of supported containers. /// public static List Containers { get { if (containers == null) { containers = InteropUtilities.ToListFromIterator(HBFunctions.hb_container_get_next, HandBrakeUnitConversionHelpers.NativeToContainer); } return containers; } } /// /// Gets a value indicating whether SRT subtitles can be burnt in. /// public static bool CanBurnSrt { get { return HBFunctions.hb_subtitle_can_burn((int)hb_subtitle_s_subsource.IMPORTSRT) > 0; } } /// /// Gets a value indicating whether SRT subtitles can be burnt in. /// public static bool CanBurnSSA { get { return HBFunctions.hb_subtitle_can_burn((int)hb_subtitle_s_subsource.IMPORTSSA) > 0; } } /// /// 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 audio encoder with the specified codec ID. /// /// /// The ID of the audio encoder. /// /// /// The requested audio encoder. /// public static HBAudioEncoder GetAudioEncoder(int codecId) { return AudioEncoders.SingleOrDefault(e => e.Id == codecId); } public static HBAudioEncoder GetAutoPassthruEncoder(int inputCodec, int copyMask, int fallback, int muxer) { int encoder = HBFunctions.hb_autopassthru_get_encoder(inputCodec, copyMask, fallback, muxer); return GetAudioEncoder(encoder); } /// /// Gets the video encoder with the specified short name. /// /// /// The name of the video encoder. /// /// /// The requested video encoder. /// public static HBVideoEncoder GetVideoEncoder(string shortName) { return VideoEncoders.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); } /// /// Gets the mixdown with the specified ID. /// /// The mixdown ID. /// The requested mixdown. public static HBMixdown GetMixdown(int id) { return Mixdowns.SingleOrDefault(m => m.Id == id); } /// /// Gets the container with the specified short name. /// /// /// The name of the container. /// /// /// The requested container. /// public static HBContainer GetContainer(string shortName) { return Containers.SingleOrDefault(c => c.ShortName == shortName); } /// /// Returns true if the subtitle source type can be set to forced only. /// /// /// The subtitle source type (SSA, VobSub, etc) /// /// /// True if the subtitle source type can be set to forced only. /// public static bool SubtitleCanSetForcedOnly(int source) { return HBFunctions.hb_subtitle_can_force(source) > 0; } /// /// Returns true if the subtitle source type can be burned in. /// /// /// The subtitle source type (SSA, VobSub, etc) /// /// /// True if the subtitle source type can be burned in. /// public static bool SubtitleCanBurn(int source) { return HBFunctions.hb_subtitle_can_burn(source) > 0; } /// /// Returns true if the subtitle type can be passed through using the given muxer. /// /// /// The subtitle source type (SSA, VobSub, etc) /// /// /// The ID of the muxer. /// /// /// True if the subtitle type can be passed through with the given muxer. /// public static bool SubtitleCanPassthrough(int subtitleSourceType, int muxer) { return HBFunctions.hb_subtitle_can_pass(subtitleSourceType, muxer) > 0; } /// /// Gets the subtitle source type's name. /// /// /// The subtitle source type (SSA, VobSub, etc). /// /// /// The name of the subtitle source. /// public static string GetSubtitleSourceName(int source) { switch ((hb_subtitle_s_subsource)source) { case hb_subtitle_s_subsource.CC608SUB: return "CC608"; case hb_subtitle_s_subsource.CC708SUB: return "CC708"; case hb_subtitle_s_subsource.IMPORTSRT: return "SRT"; case hb_subtitle_s_subsource.IMPORTSSA: case hb_subtitle_s_subsource.SSASUB: return "SSA"; case hb_subtitle_s_subsource.TX3GSUB: return "TX3G"; case hb_subtitle_s_subsource.UTF8SUB: return "UTF8"; case hb_subtitle_s_subsource.VOBSUB: return "VobSub"; case hb_subtitle_s_subsource.PGSSUB: return "PGS"; default: return string.Empty; } } /// /// Determines if the given encoder is compatible with the given track. /// /// /// The codec Id. /// /// /// The encoder to examine. /// /// /// True if the given encoder is compatible with the given audio track. /// /// /// Only works with passthrough encoders. /// public static bool AudioEncoderIsCompatible(int codecId, HBAudioEncoder encoder) { return (codecId & encoder.Id) > 0; } /// /// Determines if the given mixdown supports the given channel layout. /// /// /// The mixdown to evaluate. /// /// /// The channel layout to evaluate. /// /// /// True if the mixdown supports the given channel layout. /// public static bool MixdownHasRemixSupport(HBMixdown mixdown, ulong layout) { return HBFunctions.hb_mixdown_has_remix_support(mixdown.Id, layout) > 0; } /// /// Determines if the given encoder supports the given mixdown. /// /// /// The mixdown to evaluate. /// /// /// The encoder to evaluate. /// /// /// True if the encoder supports the mixdown. /// public static bool MixdownHasCodecSupport(HBMixdown mixdown, HBAudioEncoder encoder) { return HBFunctions.hb_mixdown_has_codec_support(mixdown.Id, (uint)encoder.Id) > 0; } /// /// Determines if a mixdown is available for a given track and encoder. /// /// /// The mixdown to evaluate. /// /// /// The encoder to evaluate. /// /// channel layout of the source track /// True if available. public static bool MixdownIsSupported(HBMixdown mixdown, HBAudioEncoder encoder, long channelLayout) { return HBFunctions.hb_mixdown_is_supported(mixdown.Id, (uint)encoder.Id, (uint)channelLayout) > 0; } /// /// Determines if DRC can be applied to the given track with the given encoder. /// /// /// The handle. /// /// /// The track Number. /// /// /// The encoder to use for DRC. /// /// /// The title. /// /// /// True if DRC can be applied to the track with the given encoder. /// public static bool CanApplyDrc(IntPtr handle, int trackNumber, HBAudioEncoder encoder, int title) { return HBFunctions.hb_audio_can_apply_drc2(handle, title, trackNumber, encoder.Id) > 0; } /// /// Determines if the given input audio codec can be passed through. /// /// /// The input codec to consider. /// /// /// True if the codec can be passed through. /// public static bool CanPassthroughAudio(int codecId) { return (codecId & NativeConstants.HB_ACODEC_PASS_MASK) > 0; } /// /// 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, ulong layout) { if (mixdown == null || encoder == null) { return null; } int sanitizedMixdown = HBFunctions.hb_mixdown_get_best((uint)encoder.Id, layout, mixdown.Id); if (sanitizedMixdown != -1) { return Mixdowns.Single(m => m.Id == sanitizedMixdown); } return Mixdowns.FirstOrDefault(); // "none" } /// /// 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, ulong layout) { int defaultMixdown = HBFunctions.hb_mixdown_get_default((uint)encoder.Id, layout); return Mixdowns.Single(m => m.Id == defaultMixdown); } /// /// Sanitizes the given sample rate for the given encoder. /// /// The encoder. /// The sample rate to sanitize. /// The sanitized sample rate. public static int SanitizeSampleRate(HBAudioEncoder encoder, int sampleRate) { return HBFunctions.hb_audio_samplerate_find_closest(sampleRate, (uint)encoder.Id); } /// /// 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_audio_bitrate_get_limits((uint)encoder.Id, sampleRate, mixdown.Id, ref low, ref high); return new BitrateLimits(low, high); } /// /// Gets the video quality limits for the given video codec. /// /// /// The video encoder to check. /// /// /// Limits on the video quality for the encoder. /// public static VideoQualityLimits GetVideoQualityLimits(HBVideoEncoder encoder) { float low = 0; float high = 0; float granularity = 0; int direction = 0; HBFunctions.hb_video_quality_get_limits((uint)encoder.Id, ref low, ref high, ref granularity, ref direction); return new VideoQualityLimits(low, high, granularity, direction == 0); } /// /// 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_audio_bitrate_get_best((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_audio_bitrate_get_default((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. /// public static RangeLimits GetAudioQualityLimits(int encoderId) { float low = 0, high = 0, granularity = 0; int direction = 0; HBFunctions.hb_audio_quality_get_limits((uint)encoderId, ref low, ref high, ref granularity, ref direction); return new RangeLimits(direction == 0, granularity, high, low); } /// /// Gets limits on audio compression for a given encoder. /// /// /// The audio encoder ID. /// /// /// Limits on the audio compression for the given encoder. /// public static RangeLimits GetAudioCompressionLimits(int encoderId) { float low = 0, high = 0, granularity = 0; int direction = 0; HBFunctions.hb_audio_compression_get_limits((uint)encoderId, ref low, ref high, ref granularity, ref direction); return new RangeLimits(direction == 0, granularity, high, low); } /// /// The get default quality. /// /// /// The encoder. /// /// /// The . /// public static double GetDefaultQuality(HBAudioEncoder encoder) { return HBFunctions.hb_audio_quality_get_default((uint)encoder.Id); } /// /// The get default audio compression. /// /// /// The encoder. /// /// /// The . /// public static double GetDefaultAudioCompression(HBAudioEncoder encoder) { return HBFunctions.hb_audio_compression_get_default((uint)encoder.Id); } public static uint BuildCopyMask(bool audioAllowMP2Pass, bool audioAllowMP3Pass, bool audioAllowAACPass, bool audioAllowAC3Pass, bool audioAllowDTSPass, bool audioAllowDTSHDPass, bool audioAllowEac3Pass, bool audioAllowFlacPass, bool audioAllowTruehdPass) { uint mask = 0; if (audioAllowMP2Pass) { mask |= NativeConstants.HB_ACODEC_MP2_PASS; } if (audioAllowMP3Pass) { mask |= NativeConstants.HB_ACODEC_MP3_PASS; } if (audioAllowAACPass) { mask |= NativeConstants.HB_ACODEC_AAC_PASS; } if (audioAllowAC3Pass) { mask |= NativeConstants.HB_ACODEC_AC3_PASS; } if (audioAllowDTSPass) { mask |= NativeConstants.HB_ACODEC_DCA_PASS; } if (audioAllowDTSHDPass) { mask |= NativeConstants.HB_ACODEC_DCA_HD_PASS; } if (audioAllowEac3Pass) { mask |= NativeConstants.HB_ACODEC_EAC3_PASS; } if (audioAllowFlacPass) { mask |= NativeConstants.HB_ACODEC_FLAC_PASS; } if (audioAllowTruehdPass) { mask |= NativeConstants.HB_ACODEC_TRUEHD_PASS; } return mask; } public static List GetQsvAdaptorList() { if (HandBrakeHardwareEncoderHelper.IsQsvAvailable) { IntPtr gpuListPtr = HBFunctions.hb_qsv_adapters_list(); List gpuList = InteropUtilities.ToListFromHandBrakeList(gpuListPtr); return gpuList; } return new List(); } } }