/// <summary>
        /// Applies an audio encoding to a native audio encoding base structure.
        /// </summary>
        /// <param name="encoding">The encoding to apply.</param>
        /// <param name="baseStruct">The base native structure.</param>
        /// <param name="outputTrack">The output track number (0-based).</param>
        /// <param name="allocatedMemory">The collection of allocated memory.</param>
        /// <returns>The resulting native audio structure.</returns>
        private hb_audio_s ConvertAudioBack(AudioEncoding encoding, hb_audio_s baseStruct, int outputTrack, List<IntPtr> allocatedMemory)
        {
            hb_audio_s nativeAudio = baseStruct;
            HBAudioEncoder encoder = Encoders.GetAudioEncoder(encoding.Encoder);

            nativeAudio.config.output.track = outputTrack;
            nativeAudio.config.output.codec = (uint)encoder.Id;

            if (!encoder.IsPassthrough)
            {
                if (encoding.SampleRateRaw == 0)
                {
                    nativeAudio.config.output.samplerate = nativeAudio.config.input.samplerate;
                }
                else
                {
                    nativeAudio.config.output.samplerate = encoding.SampleRateRaw;
                }

                HBMixdown mixdown = Encoders.GetMixdown(encoding.Mixdown);
                nativeAudio.config.output.mixdown = mixdown.Id;

                if (encoding.EncodeRateType == AudioEncodeRateType.Bitrate)
                {
                    // 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 if (encoding.EncodeRateType == AudioEncodeRateType.Quality)
                {
                    // 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))
            {
                IntPtr encodingNamePtr = Marshal.StringToHGlobalAnsi(encoding.Name);
                nativeAudio.config.output.name = encodingNamePtr;
                allocatedMemory.Add(encodingNamePtr);
            }

            nativeAudio.padding = new byte[MarshalingConstants.AudioPaddingBytes];

            return nativeAudio;
        }
        /// <summary>
        /// Applies an audio encoding to a native audio encoding base structure.
        /// </summary>
        /// <param name="encoding">The encoding to apply.</param>
        /// <param name="baseStruct">The base native structure.</param>
        /// <param name="outputTrack">The output track number (0-based).</param>
        /// <param name="allocatedMemory">The collection of allocated memory.</param>
        /// <returns>The resulting native audio structure.</returns>
        private hb_audio_s ConvertAudioBack(AudioEncoding encoding, hb_audio_s baseStruct, int outputTrack, List<IntPtr> allocatedMemory)
        {
            hb_audio_s nativeAudio = baseStruct;
            HBAudioEncoder encoder = Encoders.GetAudioEncoder(encoding.Encoder);

            if (encoder == null)
            {
                throw new InvalidOperationException("Could not find audio encoder " + encoding.Name);
            }

            bool isPassthrough = encoder.IsPassthrough;

            HBAudioEncoder inputCodec = Encoders.GetAudioEncoder((int)baseStruct.config.input.codec);

            uint outputCodec = (uint)encoder.Id;
            if (encoding.PassthroughIfPossible &&
                (encoder.Id == baseStruct.config.input.codec ||
                    inputCodec != null && (inputCodec.ShortName.ToLowerInvariant().Contains("aac") && encoder.ShortName.ToLowerInvariant().Contains("aac") ||
                    inputCodec.ShortName.ToLowerInvariant().Contains("mp3") && encoder.ShortName.ToLowerInvariant().Contains("mp3"))) &&
                (inputCodec.Id & NativeConstants.HB_ACODEC_PASS_MASK) > 0)
            {
                outputCodec = baseStruct.config.input.codec | NativeConstants.HB_ACODEC_PASS_FLAG;
                isPassthrough = true;
            }

            nativeAudio.config.output.track = outputTrack;
            nativeAudio.config.output.codec = outputCodec;
            nativeAudio.config.output.compression_level = -1;
            nativeAudio.config.output.samplerate = nativeAudio.config.input.samplerate;
            nativeAudio.config.output.dither_method = -1;

            if (!isPassthrough)
            {
                if (encoding.SampleRateRaw != 0)
                {
                    nativeAudio.config.output.samplerate = encoding.SampleRateRaw;
                }

                HBMixdown mixdown = Encoders.GetMixdown(encoding.Mixdown);
                nativeAudio.config.output.mixdown = mixdown.Id;

                if (encoding.EncodeRateType == AudioEncodeRateType.Bitrate)
                {
                    // Disable quality targeting.
                    nativeAudio.config.output.quality = -3;

                    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_audio_bitrate_get_default(
                            nativeAudio.config.output.codec,
                            nativeAudio.config.output.samplerate,
                            nativeAudio.config.output.mixdown);
                    }
                    else
                    {
                        nativeAudio.config.output.bitrate = encoding.Bitrate;
                    }
                }
                else if (encoding.EncodeRateType == AudioEncodeRateType.Quality)
                {
                    // 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))
            {
                IntPtr encodingNamePtr = Marshal.StringToHGlobalAnsi(encoding.Name);
                nativeAudio.config.output.name = encodingNamePtr;
                allocatedMemory.Add(encodingNamePtr);
            }

            if (nativeAudio.padding == null)
            {
                nativeAudio.padding = new byte[MarshalingConstants.AudioPaddingBytes];
            }

            return nativeAudio;
        }
        /// <summary>
        /// Applies an audio encoding to a native audio encoding base structure.
        /// </summary>
        /// <param name="encoding">The encoding to apply.</param>
        /// <param name="baseStruct">The base native structure.</param>
        /// <param name="outputTrack">The output track number (0-based).</param>
        /// <param name="allocatedMemory">The collection of allocated memory.</param>
        /// <returns>The resulting native audio structure.</returns>
        private hb_audio_s ConvertAudioBack(AudioEncoding encoding, hb_audio_s baseStruct, int outputTrack, List<IntPtr> allocatedMemory)
        {
            hb_audio_s nativeAudio = baseStruct;

            nativeAudio.config.output.track = outputTrack;

            if (encoding.Encoder == AudioEncoder.Passthrough)
            {
                // If we've been given a general "Passthrough" codec, see if it's valid for this input track.
                uint audioCodec = baseStruct.config.input.codec & NativeConstants.HB_ACODEC_PASS_MASK;
                if (audioCodec > 0)
                {
                    // We can do passthrough for this input.
                    //nativeAudio.config.output.codec = NativeConstants.HB_ACODEC_PASS_MASK | NativeConstants.HB_ACODEC_PASS_FLAG;
                    nativeAudio.config.output.codec = audioCodec | NativeConstants.HB_ACODEC_PASS_FLAG;
                }
                else
                {
                    // We can't do passthrough for this input. Set it to a DTS passthrough, which will cause the track to be dropped.
                    nativeAudio.config.output.codec = NativeConstants.HB_ACODEC_DCA_PASS;
                }
            }
            else
            {
                nativeAudio.config.output.codec = Converters.AudioEncoderToNative(encoding.Encoder);
            }

            if (!Utilities.IsPassthrough(encoding.Encoder))
            {
                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)
                {
                    nativeAudio.config.output.mixdown = HBFunctions.hb_get_default_mixdown(nativeAudio.config.output.codec, nativeAudio.config.input.channel_layout);
                }
                else
                {
                    nativeAudio.config.output.mixdown = Converters.MixdownToNative(encoding.Mixdown);
                }

                if (encoding.SampleRateRaw == 0)
                {
                    nativeAudio.config.output.samplerate = nativeAudio.config.input.samplerate;
                }
                else
                {
                    nativeAudio.config.output.samplerate = encoding.SampleRateRaw;
                }
            }

            if (!string.IsNullOrEmpty(encoding.Name))
            {
                IntPtr encodingNamePtr = Marshal.StringToHGlobalAnsi(encoding.Name);
                nativeAudio.config.output.name = encodingNamePtr;
                allocatedMemory.Add(encodingNamePtr);
            }

            nativeAudio.padding = new byte[MarshalingConstants.AudioPaddingBytes];

            return nativeAudio;
        }
        /// <summary>
        /// Applies an audio encoding to a native audio encoding base structure.
        /// </summary>
        /// <param name="encoding">The encoding to apply.</param>
        /// <param name="baseStruct">The base native structure.</param>
        /// <param name="outputTrack">The output track number (0-based).</param>
        /// <param name="allocatedMemory">The collection of allocated memory.</param>
        /// <returns>The resulting native audio structure.</returns>
        private hb_audio_s ConvertAudioBack(AudioEncoding encoding, hb_audio_s baseStruct, int outputTrack, List<IntPtr> allocatedMemory)
        {
            hb_audio_s nativeAudio = baseStruct;

            nativeAudio.config.output.track = outputTrack;
            nativeAudio.config.output.codec = Converters.AudioEncoderToNative(encoding.Encoder);

            if (!Utilities.IsPassthrough(encoding.Encoder))
            {
                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)
                {
                    nativeAudio.config.output.mixdown = HBFunctions.hb_get_default_mixdown(nativeAudio.config.output.codec, nativeAudio.config.input.channel_layout);
                }
                else
                {
                    nativeAudio.config.output.mixdown = Converters.MixdownToNative(encoding.Mixdown);
                }

                if (encoding.SampleRateRaw == 0)
                {
                    nativeAudio.config.output.samplerate = nativeAudio.config.input.samplerate;
                }
                else
                {
                    nativeAudio.config.output.samplerate = encoding.SampleRateRaw;
                }
            }

            if (!string.IsNullOrEmpty(encoding.Name))
            {
                IntPtr encodingNamePtr = Marshal.StringToHGlobalAnsi(encoding.Name);
                nativeAudio.config.output.name = encodingNamePtr;
                allocatedMemory.Add(encodingNamePtr);
            }

            nativeAudio.padding = new byte[MarshalingConstants.AudioPaddingBytes];

            return nativeAudio;
        }