/// <summary> /// The calculate bitrate limits. /// </summary> private void SetupBitrateLimits() { // Base set of bitrates available. List <int> audioBitrates = HandBrakeEncoderHelpers.AudioBitrates; // Defaults int max = 256; int low = 32; // Based on the users settings, find the high and low bitrates. HBAudioEncoder hbaenc = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(this.Encoder)); HBRate rate = HandBrakeEncoderHelpers.AudioSampleRates.FirstOrDefault(t => t.Name == this.SampleRate.ToString(CultureInfo.InvariantCulture)); HBMixdown mixdown = this.mixDown ?? HandBrakeEncoderHelpers.GetMixdown("dpl2"); BitrateLimits limits = HandBrakeEncoderHelpers.GetBitrateLimits(hbaenc, rate != null ? rate.Rate : 48000, mixdown); if (limits != null) { max = limits.High; low = limits.Low; } // Return the subset of available bitrates. List <int> subsetBitrates = audioBitrates.Where(b => b <= max && b >= low).ToList(); this.bitrates = subsetBitrates; this.NotifyOfPropertyChange(() => this.Bitrates); // If the subset does not contain the current bitrate, request the default. if (!subsetBitrates.Contains(this.Bitrate)) { this.Bitrate = HandBrakeEncoderHelpers.GetDefaultBitrate(hbaenc, rate != null ? rate.Rate : 48000, mixdown); } }
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 = Encoders.SanitizeMixdown(mixdownLimits, this.HBAudioEncoder, track.ChannelLayout); } bitrateLimits = Encoders.GetBitrateLimits(this.HBAudioEncoder, sampleRateLimits, mixdownLimits); } } BitrateLimits encoderBitrateLimits = CodecUtilities.GetAudioEncoderLimits(this.HBAudioEncoder); this.bitrateChoices.Add(new BitrateChoiceViewModel { Bitrate = 0, IsCompatible = true }); foreach (int bitrateChoice in Encoders.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(() => this.BitrateChoices); this.selectedBitrate = this.BitrateChoices.SingleOrDefault(b => b.Bitrate == oldBitrate); if (this.selectedBitrate == null) { this.selectedBitrate = this.BitrateChoices[0]; } //this.selectedBitrate = this.BitrateChoices.Single(b => b.Bitrate == oldBitrate); this.RaisePropertyChanged(() => this.SelectedBitrate); }
public AudioEncodingViewModel(AudioEncoding audioEncoding, SourceTitle selectedTitle, List <int> chosenAudioTracks, AudioPanelViewModel audioPanelVM) { this.initializing = true; this.audioPanelVM = audioPanelVM; this.targetStreams = new ObservableCollection <TargetStreamViewModel>(); this.targetStreamIndex = audioEncoding.InputNumber; this.SetChosenTracks(chosenAudioTracks, selectedTitle); this.audioEncoders = new List <AudioEncoderViewModel>(); this.mixdownChoices = new List <MixdownViewModel>(); this.RefreshEncoderChoices(); this.presetChangeSubscription = this.presetsService.WhenAnyValue(x => x.SelectedPreset.Preset.EncodingProfile) .Subscribe(profile => { this.containerSubscription?.Dispose(); this.containerSubscription = profile.WhenAnyValue(x => x.ContainerName) .Skip(1) .Subscribe(_ => { this.RefreshEncoderChoices(isContainerChange: true); }); this.audioPanelVM.SuppressProfileEdits = true; this.RefreshEncoderChoices(); this.audioPanelVM.SuppressProfileEdits = false; }); HBAudioEncoder hbAudioEncoder = HandBrakeEncoderHelpers.GetAudioEncoder(audioEncoding.Encoder); if (hbAudioEncoder.IsPassthrough) { this.selectedAudioEncoder = this.audioEncoders[0]; this.selectedPassthrough = audioEncoding.Encoder; } else { this.selectedAudioEncoder = this.audioEncoders.Skip(1).FirstOrDefault(e => e.Encoder.ShortName == audioEncoding.Encoder); this.selectedPassthrough = "copy"; } if (this.selectedAudioEncoder == null) { this.selectedAudioEncoder = this.audioEncoders[1]; } this.RefreshMixdownChoices(); this.RefreshBitrateChoices(); this.RefreshSampleRateChoices(); this.SelectMixdown(HandBrakeEncoderHelpers.GetMixdown(audioEncoding.Mixdown)); this.sampleRate = audioEncoding.SampleRateRaw; if (!this.HBAudioEncoder.SupportsQuality) { this.encodeRateType = AudioEncodeRateType.Bitrate; } else { this.encodeRateType = audioEncoding.EncodeRateType; } this.audioQuality = audioEncoding.Quality; if (audioEncoding.Compression >= 0) { this.audioCompression = audioEncoding.Compression; } else { this.audioCompression = this.HBAudioEncoder.DefaultCompression; } this.selectedBitrate = this.BitrateChoices.SingleOrDefault(b => b.Bitrate == audioEncoding.Bitrate); if (this.selectedBitrate == null) { this.selectedBitrate = this.BitrateChoices.First(); } this.gain = audioEncoding.Gain; this.drc = audioEncoding.Drc; this.passthroughIfPossible = audioEncoding.PassthroughIfPossible; this.name = audioEncoding.Name; // EncoderSettingsVisible this.WhenAnyValue(x => x.SelectedAudioEncoder, x => x.SelectedPassthrough, (audioEncoder, passthrough) => { if (audioEncoder == null) { return(false); } if (passthrough == null) { return(false); } return(!GetHBAudioEncoder(audioEncoder, passthrough).IsPassthrough); }).ToProperty(this, x => x.EncoderSettingsVisible, out this.encoderSettingsVisible); // AudioCompressionVisible this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { return(!audioEncoder.IsPassthrough && audioEncoder.Encoder.SupportsCompression); }).ToProperty(this, x => x.AudioCompressionVisible, out this.audioCompressionVisible); // PassthroughIfPossibleVisible this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(false); } if (HandBrakeEncoderHelpers.AudioEncoders.Any(e => e.Id == (NativeConstants.HB_ACODEC_PASS_FLAG | audioEncoder.Encoder.Id))) { return(true); } return(audioEncoder.Encoder.ShortName.ToLowerInvariant().Contains("aac") || audioEncoder.Encoder.ShortName.ToLowerInvariant().Contains("mp3")); }).ToProperty(this, x => x.PassthroughIfPossibleVisible, out this.passthroughIfPossibleVisible); // BitrateVisible this.WhenAnyValue( x => x.SelectedAudioEncoder, x => x.EncoderSettingsVisible, x => x.SelectedMixdown, x => x.EncodeRateType, (audioEncoder, encoderSettingsVisible, mixdown, encodeRateType) => { if (audioEncoder.IsPassthrough) { return(false); } if (encoderSettingsVisible && mixdown != null && encodeRateType == AudioEncodeRateType.Bitrate) { // We only need to find out if the bitrate limits exist, so pass in some normal values for sample rate and mixdown. BitrateLimits bitrateLimits = HandBrakeEncoderHelpers.GetBitrateLimits(audioEncoder.Encoder, 48000, HandBrakeEncoderHelpers.GetMixdown("dpl2")); return(bitrateLimits.High > 0); } return(false); }).ToProperty(this, x => x.BitrateVisible, out this.bitrateVisible); // BitrateLabelVisible this.WhenAnyValue(x => x.BitrateVisible, x => x.SelectedAudioEncoder, (bitrateVisible, audioEncoder) => { return(!audioEncoder.IsPassthrough && bitrateVisible && !audioEncoder.Encoder.SupportsQuality); }).ToProperty(this, x => x.BitrateLabelVisible, out this.bitrateLabelVisible); // AudioQualityVisible this.WhenAnyValue(x => x.SelectedAudioEncoder, x => x.EncodeRateType, (audioEncoder, encodeRateType) => { return(!audioEncoder.IsPassthrough && audioEncoder.Encoder.SupportsQuality && encodeRateType == AudioEncodeRateType.Quality); }).ToProperty(this, x => x.AudioQualityVisible, out this.audioQualityVisible); // AudioQualityRadioVisible this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { return(!audioEncoder.IsPassthrough && audioEncoder.Encoder.SupportsQuality); }).ToProperty(this, x => x.AudioQualityRadioVisible, out this.audioQualityRadioVisible); // AudioQualityMinimum this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(0); } return(Math.Round(audioEncoder.Encoder.QualityLimits.Low, RangeRoundDigits)); }).ToProperty(this, x => x.AudioQualityMinimum, out this.audioQualityMinimum); // AudioQualityMaximum this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(0); } return(Math.Round(audioEncoder.Encoder.QualityLimits.High, RangeRoundDigits)); }).ToProperty(this, x => x.AudioQualityMaximum, out this.audioQualityMaximum); // AudioQualityGranularity this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(0); } return(Math.Round(audioEncoder.Encoder.QualityLimits.Granularity, RangeRoundDigits)); }).ToProperty(this, x => x.AudioQualityGranularity, out this.audioQualityGranularity); // AudioQualityToolTip this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(string.Empty); } string directionSentence; if (audioEncoder.Encoder.QualityLimits.Ascending) { directionSentence = EncodingRes.AscendingQualityToolTip; } else { directionSentence = EncodingRes.DescendingQualityToolTip; } return(string.Format( EncodingRes.AudioQualityToolTip, directionSentence, audioEncoder.Encoder.QualityLimits.Low, audioEncoder.Encoder.QualityLimits.High)); }).ToProperty(this, x => x.AudioQualityToolTip, out this.audioQualityToolTip); // AudioCompressionMinimum this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(0); } return(Math.Round(audioEncoder.Encoder.CompressionLimits.Low, RangeRoundDigits)); }).ToProperty(this, x => x.AudioCompressionMinimum, out this.audioCompressionMinimum); // AudioCompressionMaximum this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(0); } return(Math.Round(audioEncoder.Encoder.CompressionLimits.High, RangeRoundDigits)); }).ToProperty(this, x => x.AudioCompressionMaximum, out this.audioCompressionMaximum); // AudioCompressionGranularity this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(0); } return(Math.Round(audioEncoder.Encoder.CompressionLimits.Granularity, RangeRoundDigits)); }).ToProperty(this, x => x.AudioCompressionGranularity, out this.audioCompressionGranularity); // AudioCompressionToolTip this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(string.Empty); } string directionSentence; if (audioEncoder.Encoder.QualityLimits.Ascending) { directionSentence = EncodingRes.AscendingCompressionToolTip; } else { directionSentence = EncodingRes.DescendingCompressionToolTip; } return(string.Format( EncodingRes.AudioCompressionToolTip, directionSentence, audioEncoder.Encoder.CompressionLimits.Low, audioEncoder.Encoder.CompressionLimits.High)); }).ToProperty(this, x => x.AudioCompressionToolTip, out this.audioCompressionToolTip); // PassthroughChoicesVisible this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { return(audioEncoder.IsPassthrough); }).ToProperty(this, x => x.PassthroughChoicesVisible, out this.passthroughChoicesVisible); this.selectedTitleSubscription = this.main.WhenAnyValue(x => x.SelectedTitle) .Skip(1) .Subscribe(_ => { this.RefreshFromNewInput(); }); this.audioTrackChangedSubscription = this.main.AudioTracks.Connect().WhenAnyPropertyChanged().Subscribe(_ => { this.RefreshFromNewInput(); }); Config.Observables.ShowAudioTrackNameField.ToProperty(this, x => x.NameVisible, out this.nameVisible); this.initializing = false; }