/// <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_audio_bitrate_get_best((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_audio_bitrate_get_default((uint)encoder.Id, sampleRate, mixdown.Id)); }
/// <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, ulong layout) { int sanitizedMixdown = HBFunctions.hb_mixdown_get_best((uint)encoder.Id, layout, mixdown.Id); return(Mixdowns.Single(m => m.Id == sanitizedMixdown)); }
/// <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_audio_bitrate_get_limits((uint)encoder.Id, sampleRate, mixdown.Id, ref low, ref high); return(new BitrateLimits { Low = low, High = high }); }
/// <summary> /// Determines if the given mixdown supports the given channel layout. /// </summary> /// <param name="mixdown">The mixdown to evaluate.</param> /// <param name="layout">The channel layout to evaluate.</param> /// <returns>True if the mixdown supports the given channel layout.</returns> public static bool MixdownHasRemixSupport(HBMixdown mixdown, ulong layout) { return(HBFunctions.hb_mixdown_has_remix_support(mixdown.Id, layout) > 0); }
/// <summary> /// Determines if the given encoder supports the given mixdown. /// </summary> /// <param name="mixdown">The mixdown to evaluate.</param> /// <param name="encoder">The encoder to evaluate.</param> /// <returns>True if the encoder supports the mixdown.</returns> public static bool MixdownHasCodecSupport(HBMixdown mixdown, HBAudioEncoder encoder) { return(HBFunctions.hb_mixdown_has_codec_support(mixdown.Id, (uint)encoder.Id) > 0); }
/// <summary> /// The create audio. /// </summary> /// <param name="job"> /// The job. /// </param> /// <returns> /// The <see cref="Audio"/>. /// </returns> private static Audio CreateAudio(EncodeTask job) { Audio audio = new Audio(); List <uint> copyMaskList = new List <uint>(); if (job.AllowedPassthruOptions.AudioAllowAACPass) { copyMaskList.Add(NativeConstants.HB_ACODEC_AAC_PASS); } if (job.AllowedPassthruOptions.AudioAllowAC3Pass) { copyMaskList.Add(NativeConstants.HB_ACODEC_AC3_PASS); } if (job.AllowedPassthruOptions.AudioAllowDTSHDPass) { copyMaskList.Add(NativeConstants.HB_ACODEC_DCA_HD_PASS); } if (job.AllowedPassthruOptions.AudioAllowDTSPass) { copyMaskList.Add(NativeConstants.HB_ACODEC_DCA_PASS); } if (job.AllowedPassthruOptions.AudioAllowEAC3Pass) { copyMaskList.Add(NativeConstants.HB_ACODEC_EAC3_PASS); } if (job.AllowedPassthruOptions.AudioAllowFlacPass) { copyMaskList.Add(NativeConstants.HB_ACODEC_FLAC_PASS); } if (job.AllowedPassthruOptions.AudioAllowMP3Pass) { copyMaskList.Add(NativeConstants.HB_ACODEC_MP3_PASS); } if (job.AllowedPassthruOptions.AudioAllowTrueHDPass) { copyMaskList.Add(NativeConstants.HB_ACODEC_TRUEHD_PASS); } audio.CopyMask = copyMaskList.ToArray(); HBAudioEncoder audioEncoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(job.AllowedPassthruOptions.AudioEncoderFallback)); audio.FallbackEncoder = audioEncoder.Id; audio.AudioList = new List <Interop.Json.Encode.AudioTrack>(); foreach (AudioTrack item in job.AudioTracks) { HBAudioEncoder encoder = HandBrakeEncoderHelpers.GetAudioEncoder(ApplicationServices.Utilities.Converters.GetCliAudioEncoder(item.Encoder)); Validate.NotNull(encoder, "Unrecognized audio encoder:" + item.Encoder); HBMixdown mixdown = HandBrakeEncoderHelpers.GetMixdown(EnumHelper <Mixdown> .GetShortName(item.MixDown)); Validate.NotNull(mixdown, "Unrecognized audio mixdown:" + item.MixDown); HBRate sampleRate = HandBrakeEncoderHelpers.AudioSampleRates.FirstOrDefault(s => s.Name == item.SampleRate.ToString(CultureInfo.InvariantCulture)); HandBrake.ApplicationServices.Interop.Json.Encode.AudioTrack audioTrack = new HandBrake.ApplicationServices.Interop.Json.Encode.AudioTrack { Track = (item.Track.HasValue ? item.Track.Value : 0) - 1, DRC = item.DRC, Encoder = encoder.Id, Gain = item.Gain, Mixdown = mixdown.Id, NormalizeMixLevel = false, Samplerate = sampleRate != null ? sampleRate.Rate : 0, Name = item.TrackName, }; if (!item.IsPassthru) { if (item.EncoderRateType == AudioEncoderRateType.Quality) { audioTrack.Quality = item.Quality; } if (item.EncoderRateType == AudioEncoderRateType.Bitrate) { audioTrack.Bitrate = item.Bitrate; } } audio.AudioList.Add(audioTrack); } return(audio); }
private Audio CreateAudio(EncodeTask job) { Audio audio = new Audio(); List <string> copyMaskList = new List <string>(); if (job.AudioPassthruOptions.AudioAllowAACPass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.AacPassthru)); } if (job.AudioPassthruOptions.AudioAllowAC3Pass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.Ac3Passthrough)); } if (job.AudioPassthruOptions.AudioAllowDTSHDPass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.DtsHDPassthrough)); } if (job.AudioPassthruOptions.AudioAllowDTSPass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.DtsPassthrough)); } if (job.AudioPassthruOptions.AudioAllowEAC3Pass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.EAc3Passthrough)); } if (job.AudioPassthruOptions.AudioAllowFlacPass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.FlacPassthru)); } if (job.AudioPassthruOptions.AudioAllowMP3Pass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.Mp3Passthru)); } if (job.AudioPassthruOptions.AudioAllowTrueHDPass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.TrueHDPassthrough)); } if (job.AudioPassthruOptions.AudioAllowMP2Pass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.Mp2Passthru)); } audio.CopyMask = copyMaskList.ToArray(); HBAudioEncoder audioEncoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(job.AudioPassthruOptions.AudioEncoderFallback)); audio.FallbackEncoder = audioEncoder?.ShortName; Validate.NotNull(audio.FallbackEncoder, string.Format("Unrecognized audio encoder: {0} \n", job.AudioPassthruOptions.AudioEncoderFallback)); audio.AudioList = new List <HandBrake.Interop.Interop.Json.Encode.AudioTrack>(); foreach (AudioTrack item in job.AudioTracks) { HBAudioEncoder encoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(item.Encoder)); Validate.NotNull(encoder, "Unrecognized audio encoder:" + item.Encoder); if (item.IsPassthru && (item.ScannedTrack.Codec & encoder.Id) == 0) { // We have an unsupported passthru. Rather than let libhb drop the track, switch it to the fallback. encoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(job.AudioPassthruOptions.AudioEncoderFallback)); } HBMixdown mixdown = HandBrakeEncoderHelpers.GetMixdown(item.MixDown); HBRate sampleRate = HandBrakeEncoderHelpers.AudioSampleRates.FirstOrDefault(s => s.Name == item.SampleRate.ToString(CultureInfo.InvariantCulture)); HandBrake.Interop.Interop.Json.Encode.AudioTrack audioTrack = new HandBrake.Interop.Interop.Json.Encode.AudioTrack { Track = (item.Track.HasValue ? item.Track.Value : 0) - 1, DRC = item.DRC, Encoder = encoder.ShortName, Gain = item.Gain, Mixdown = mixdown != null ? mixdown.Id : -1, NormalizeMixLevel = false, Samplerate = sampleRate != null ? sampleRate.Rate : 0, Name = !string.IsNullOrEmpty(item.TrackName) ? item.TrackName : null, }; if (!item.IsPassthru) { if (item.EncoderRateType == AudioEncoderRateType.Quality) { audioTrack.Quality = item.Quality; } if (item.EncoderRateType == AudioEncoderRateType.Bitrate) { audioTrack.Bitrate = item.Bitrate; } } audio.AudioList.Add(audioTrack); } return(audio); }
/// <summary> /// Determines if a mixdown is available for a given track and encoder. /// </summary> /// <param name="mixdown"> /// The mixdown to evaluate. /// </param> /// <param name="encoder"> /// The encoder to evaluate. /// </param> /// <param name="channelLayout">channel layout of the source track</param> /// <returns>True if available.</returns> public static bool MixdownIsSupported(HBMixdown mixdown, HBAudioEncoder encoder, long channelLayout) { return(HBFunctions.hb_mixdown_is_supported(mixdown.Id, (uint)encoder.Id, (uint)channelLayout) > 0); }
/// <summary> /// Initializes a new instance of the <see cref="AudioTrack"/> class. /// Create a track from a behaviour track. /// </summary> /// <param name="track"> /// The Behavior track /// </param> /// <param name="sourceTrack"> /// The source track we are dealing with. /// </param> /// <param name="fallback"> /// An encoder to fall back to. /// </param> public AudioTrack(AudioBehaviourTrack track, Audio sourceTrack, AllowedPassthru fallback, OutputFormat container) { AudioEncoder chosenEncoder = track.Encoder; HBAudioEncoder encoderInfo = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(track.Encoder)); if (track.IsPassthru && (sourceTrack.Codec & encoderInfo.Id) == 0) { chosenEncoder = fallback.AudioEncoderFallback; } if (track.IsPassthru && chosenEncoder == AudioEncoder.Passthrough) { HBAudioEncoder fallbackEncoderInfo = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(fallback.AudioEncoderFallback)); if (fallbackEncoderInfo != null) { int format = HandBrakeEncoderHelpers.GetContainer(EnumHelper <OutputFormat> .GetShortName(container)).Id; int copyMask = checked ((int)HandBrakeEncoderHelpers.BuildCopyMask( fallback.AudioAllowMP3Pass, fallback.AudioAllowAACPass, fallback.AudioAllowAC3Pass, fallback.AudioAllowDTSPass, fallback.AudioAllowDTSHDPass, fallback.AudioAllowEAC3Pass, fallback.AudioAllowFlacPass, fallback.AudioAllowTrueHDPass)); HBAudioEncoder autoPassthruEncoderOption = HandBrakeEncoderHelpers.GetAutoPassthruEncoder(sourceTrack.Codec, copyMask, fallbackEncoderInfo.Id, format); AudioEncoder autoPassthru = EnumHelper <AudioEncoder> .GetValue(autoPassthruEncoderOption.ShortName); chosenEncoder = autoPassthru; } } encoderInfo = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(chosenEncoder)); this.scannedTrack = sourceTrack; this.drc = track.DRC; this.encoder = chosenEncoder; this.gain = track.Gain; this.mixDown = track.MixDown != null ? track.MixDown.ShortName : "dpl2"; // If the mixdown isn't supported, downgrade it. if (track.IsPassthru && track.MixDown != null && encoderInfo != null && !HandBrakeEncoderHelpers.MixdownIsSupported(track.MixDown, encoderInfo, sourceTrack.ChannelLayout)) { HBMixdown changedMixdown = HandBrakeEncoderHelpers.GetDefaultMixdown(encoderInfo, (ulong)sourceTrack.ChannelLayout); if (changedMixdown != null) { this.mixDown = changedMixdown.ShortName; } } this.sampleRate = track.SampleRate; this.encoderRateType = track.EncoderRateType; this.quality = track.Quality; this.bitrate = track.Bitrate; if (!string.IsNullOrEmpty(this.scannedTrack?.Name)) { this.TrackName = this.scannedTrack.Name; } this.SetupLimits(); }
private void RefreshBitrateChoices() { if (this.SelectedAudioEncoder == null || this.SelectedMixdown == null) { return; } int oldBitrate = 0; if (this.SelectedBitrate != null) { oldBitrate = this.SelectedBitrate.Bitrate; } this.bitrateChoices = new List <BitrateChoiceViewModel>(); BitrateLimits bitrateLimits = null; // Determine if we should gray out "out of range" bitrates // Can only do this if a source is loaded if (this.main.HasVideoSource) { // Find if we're encoding a single track var track = this.GetTargetAudioTrack(); // Can only gray out bitrates if we're encoding exactly one track if (track != null) { int sampleRateLimits = this.SampleRate; if (sampleRateLimits == 0) { sampleRateLimits = track.SampleRate; } HBMixdown mixdownLimits = this.SelectedMixdown.Mixdown; if (mixdownLimits.ShortName == "none" || string.IsNullOrEmpty(mixdownLimits.ShortName)) { mixdownLimits = HandBrakeEncoderHelpers.SanitizeMixdown(mixdownLimits, this.HBAudioEncoder, (ulong)track.ChannelLayout); } bitrateLimits = HandBrakeEncoderHelpers.GetBitrateLimits(this.HBAudioEncoder, sampleRateLimits, mixdownLimits); } } BitrateLimits encoderBitrateLimits = CodecUtilities.GetAudioEncoderLimits(this.HBAudioEncoder); this.bitrateChoices.Add(new BitrateChoiceViewModel { Bitrate = 0, IsCompatible = true }); foreach (int bitrateChoice in HandBrakeEncoderHelpers.AudioBitrates) { if (bitrateChoice >= encoderBitrateLimits.Low && bitrateChoice <= encoderBitrateLimits.High) { bool isCompatible = bitrateLimits == null || bitrateChoice >= bitrateLimits.Low && bitrateChoice <= bitrateLimits.High; this.bitrateChoices.Add(new BitrateChoiceViewModel { Bitrate = bitrateChoice, IsCompatible = isCompatible }); } } this.RaisePropertyChanged(nameof(this.BitrateChoices)); this.selectedBitrate = this.BitrateChoices.SingleOrDefault(b => b.Bitrate == oldBitrate); if (this.selectedBitrate == null) { this.selectedBitrate = this.BitrateChoices[0]; } this.RaisePropertyChanged(nameof(this.SelectedBitrate)); }