jlennox / NvEncSharp

MIT License
20 stars 7 forks source link

Encode Video with Custom Bitrate / Custom NvEncodeConfig #5

Closed Vince02100 closed 3 years ago

Vince02100 commented 3 years ago

Hello,

Maybe I did something wrong I don't know. I try something based on your exemple, but it's not possible to define a NvEncInitializeParams struct with NvEncConfig.

The one in the struct end with like this NvEncConfig because of this I can't compile the code. If I remove the * in your source code in Structs.cs it give me a Memory Violation Exception.

Here is my code:

        private NvEncoder CreateEncoder(Texture2D texture)
        {
            if (Initialized) return _encoder;

            _stream = File.OpenWrite(Settings.Output);

            //var desc = texture.Description;
            var encoder = OpenEncoderForDirectX(texture.Device.NativePointer);

            NvEncPresetConfig presetConfig = encoder.GetEncodePresetConfig(NvEncCodecGuids.H264, NvEncPresetGuids.LowLatencyHq);
            presetConfig.Version = NV_ENC_PRESET_CONFIG_VER;
            presetConfig.PresetCfg.RcParams.AverageBitRate = (uint)Settings.Bitrate;

            var initparams = new NvEncInitializeParams
            {
                Version = NV_ENC_INITIALIZE_PARAMS_VER,
                EncodeGuid = NvEncCodecGuids.H264,
                EncodeHeight = (uint)Settings.Height,
                EncodeWidth = (uint)Settings.Width,
                DarHeight = (uint)Settings.Height,
                DarWidth = (uint)Settings.Width,
                FrameRateNum = (uint)Settings.Framerate,
                FrameRateDen = 1,
                ReportSliceOffsets = false,
                EnableSubFrameWrite = false,
                PresetGuid = NvEncPresetGuids.LowLatencyHq,
                EncodeConfig = presetConfig.PresetCfg,
                EnableEncodeAsync = 0
            };

            encoder.InitializeEncoder(ref initparams);

            _bitstreamBuffer = encoder.CreateBitstreamBuffer();

            _encoder = encoder;
            Initialized = true;

            return encoder;
        }

Have you any idea how to achieve this ? Or maye a sample / demo that can help me ?

Thank's in advance

jlennox commented 3 years ago

he one in the struct end with like this NvEncConfig because of this I can't compile the code.

You likely need to enable unsafe code, and define your code block as unsafe. To enable this, right click your project, select properties, and enable it in the Build section.

image

You'll need to repeat this process for each build configuration (Debug and Release).

Please let me know if this helped.

Vince02100 commented 3 years ago

Hey !

Thank you for the fast reply. Damned, I tried this, but seems I forgot a step.

I will try this again tomorrow and let you know if it's working.

Vince02100 commented 3 years ago

Hello @jlennox

I did the change, enabled safe change and put the code in a unsafe block (the entire function in my case) the new code look like this (RcParams to CBR Low delay HQ)

private unsafe NvEncoder CreateEncoder(Texture2D texture)
{
    if (Initialized) return _encoder;

    _stream = File.OpenWrite(Settings.Output);

    var encoder = OpenEncoderForDirectX(texture.Device.NativePointer);

    NvEncPresetConfig presetConfig = encoder.GetEncodePresetConfig(NvEncCodecGuids.H264, NvEncPresetGuids.LowLatencyHq);
    presetConfig.Version = NV_ENC_PRESET_CONFIG_VER;
    presetConfig.PresetCfg.RcParams.RateControlMode = NvEncParamsRcMode.CbrLowdelayHq;
    presetConfig.PresetCfg.RcParams.AverageBitRate = (uint)Settings.Bitrate;
    presetConfig.PresetCfg.RcParams.MaxBitRate = (uint)Settings.Bitrate;
    presetConfig.PresetCfg.ProfileGuid = NvEncProfileGuids.H264Main;

    var initparams = new NvEncInitializeParams
    {
        Version = NV_ENC_INITIALIZE_PARAMS_VER,
        EncodeGuid = NvEncCodecGuids.H264,
        EncodeHeight = (uint)Settings.Height,
        EncodeWidth = (uint)Settings.Width,
        DarHeight = (uint)Settings.Height,
        DarWidth = (uint)Settings.Width,
        FrameRateNum = (uint)Settings.Framerate,
        FrameRateDen = 1,
        ReportSliceOffsets = false,
        EnableSubFrameWrite = false,
        PresetGuid = NvEncPresetGuids.LowLatencyHq,
        EncodeConfig = &presetConfig.PresetCfg,
        EnableEncodeAsync = 0
    };

    encoder.InitializeEncoder(ref initparams);

    _bitstreamBuffer = encoder.CreateBitstreamBuffer();

    _encoder = encoder;
    Initialized = true;

    return encoder;
}

I also added the & character before the var presetConfig at EncodeConfig = &presetConfig.PresetCfg without that, error stay the same.

Hope it's help others and thank's a lot @jlennox ;)