fcH264EncoderNVIDIA::fcH264EncoderNVIDIA(const fcH264EncoderConfig& conf, void *device, fcHWEncoderDeviceType type)
    : m_conf(conf)
{
    if (!LoadNVENCModule()) { return; }

    NVENCSTATUS stat;
    {
        NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS params;
        memset(&params, 0, sizeof(params));
        params.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER;
        params.apiVersion = NVENCAPI_VERSION;
        params.device = device;
        switch (type) {
        case fcHWEncoderDeviceType::D3D9:
        case fcHWEncoderDeviceType::D3D10:
        case fcHWEncoderDeviceType::D3D11:
        case fcHWEncoderDeviceType::D3D12:
            params.deviceType = NV_ENC_DEVICE_TYPE_DIRECTX;
            break;
        case fcHWEncoderDeviceType::CUDA:
            params.deviceType = NV_ENC_DEVICE_TYPE_CUDA;
            break;
        }
        stat = nvenc.nvEncOpenEncodeSessionEx(&params, &m_encoder);
        if (!m_encoder) {
            return;
        }
    }

    std::vector<GUID> encode_guilds;
    std::vector<GUID> profile_guilds;
    std::vector<GUID> preset_guilds;
    {
        uint32_t num_encode_guilds = 0;
        uint32_t num_profile_guilds = 0;
        uint32_t num_preset_guilds = 0;

        nvenc.nvEncGetEncodeGUIDCount(m_encoder, &num_encode_guilds);
        encode_guilds.resize(num_encode_guilds);
        nvenc.nvEncGetEncodeGUIDs(m_encoder, encode_guilds.data(), num_encode_guilds, &num_encode_guilds);

        nvenc.nvEncGetEncodeProfileGUIDCount(m_encoder, NV_ENC_CODEC_H264_GUID, &num_profile_guilds);
        profile_guilds.resize(num_profile_guilds);
        nvenc.nvEncGetEncodeProfileGUIDs(m_encoder, NV_ENC_CODEC_H264_GUID, profile_guilds.data(), num_profile_guilds, &num_profile_guilds);

        nvenc.nvEncGetEncodePresetCount(m_encoder, NV_ENC_CODEC_H264_GUID, &num_preset_guilds);
        preset_guilds.resize(num_preset_guilds);
        nvenc.nvEncGetEncodePresetGUIDs(m_encoder, NV_ENC_CODEC_H264_GUID, preset_guilds.data(), num_preset_guilds, &num_preset_guilds);
    }

    {
        NV_ENC_INITIALIZE_PARAMS params = { 0 };
        params.version = NV_ENC_INITIALIZE_PARAMS_VER;
        params.encodeGUID = NV_ENC_CODEC_H264_GUID;
        params.presetGUID = NV_ENC_PRESET_DEFAULT_GUID;
        params.encodeWidth = conf.width;
        params.encodeHeight = conf.height;
        params.darWidth = conf.width;
        params.darHeight = conf.height;
        params.frameRateNum = m_conf.target_framerate;
        params.frameRateDen = 1;
        params.enablePTD = 1;

        NV_ENC_PRESET_CONFIG preset_config = { 0 };
        preset_config.version = NV_ENC_PRESET_CONFIG_VER;
        preset_config.presetCfg.version = NV_ENC_CONFIG_VER;
        stat = nvenc.nvEncGetEncodePresetConfig(m_encoder, params.encodeGUID, params.presetGUID, &preset_config);

        NV_ENC_CONFIG encode_config = { 0 };
        encode_config.version = NV_ENC_CONFIG_VER;
        memcpy(&encode_config, &preset_config.presetCfg, sizeof(NV_ENC_CONFIG));
        encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
        params.encodeConfig = &encode_config;

        stat = nvenc.nvEncInitializeEncoder(m_encoder, &params);
    }

    {
        memset(&m_input, 0, sizeof(m_input));
        m_input.version = NV_ENC_CREATE_INPUT_BUFFER_VER;
        m_input.width = m_conf.width;
        m_input.height = m_conf.height;
        m_input.bufferFmt = NV_ENC_BUFFER_FORMAT_NV12;
        stat = nvenc.nvEncCreateInputBuffer(m_encoder, &m_input);
    }

    {
        memset(&m_output, 0, sizeof(m_output));
        m_output.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER;
        m_output.size = roundup<16>(conf.width) * roundup<16>(conf.height) * 2;
        stat = nvenc.nvEncCreateBitstreamBuffer(m_encoder, &m_output);
    }
}
Esempio n. 2
0
static int nvenc_setup_encoder(AVCodecContext *avctx)
{
    NVENCContext *ctx               = avctx->priv_data;
    NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs;
    NV_ENC_PRESET_CONFIG preset_cfg = { 0 };
    int ret;

    ctx->params.version = NV_ENC_INITIALIZE_PARAMS_VER;

    ctx->params.encodeHeight = avctx->height;
    ctx->params.encodeWidth  = avctx->width;

    if (avctx->sample_aspect_ratio.num &&
        avctx->sample_aspect_ratio.den &&
        (avctx->sample_aspect_ratio.num != 1 ||
         avctx->sample_aspect_ratio.den != 1)) {
        av_reduce(&ctx->params.darWidth,
                  &ctx->params.darHeight,
                  avctx->width * avctx->sample_aspect_ratio.num,
                  avctx->height * avctx->sample_aspect_ratio.den,
                  INT_MAX / 8);
    } else {
        ctx->params.darHeight = avctx->height;
        ctx->params.darWidth  = avctx->width;
    }

    ctx->params.frameRateNum = avctx->time_base.den;
    ctx->params.frameRateDen = avctx->time_base.num * avctx->ticks_per_frame;

    ctx->params.enableEncodeAsync = 0;
    ctx->params.enablePTD         = 1;

    ctx->params.encodeConfig = &ctx->config;

    nvec_map_preset(ctx);

    preset_cfg.version           = NV_ENC_PRESET_CONFIG_VER;
    preset_cfg.presetCfg.version = NV_ENC_CONFIG_VER;

    ret = nv->nvEncGetEncodePresetConfig(ctx->nvenc_ctx,
                                         ctx->params.encodeGUID,
                                         ctx->params.presetGUID,
                                         &preset_cfg);
    if (ret != NV_ENC_SUCCESS) {
        av_log(avctx, AV_LOG_ERROR,
               "Cannot get the preset configuration\n");
        return AVERROR_UNKNOWN;
    }

    memcpy(&ctx->config, &preset_cfg.presetCfg, sizeof(ctx->config));

    ctx->config.version = NV_ENC_CONFIG_VER;

    if (avctx->gop_size > 0) {
        if (avctx->max_b_frames > 0) {
            ctx->last_dts = -2;
            /* 0 is intra-only,
             * 1 is I/P only,
             * 2 is one B Frame,
             * 3 two B frames, and so on. */
            ctx->config.frameIntervalP = avctx->max_b_frames + 1;
        } else if (avctx->max_b_frames == 0) {
            ctx->config.frameIntervalP = 1;
        }
        ctx->config.gopLength = avctx->gop_size;
    } else if (avctx->gop_size == 0) {
        ctx->config.frameIntervalP = 0;
        ctx->config.gopLength      = 1;
    }

    if (ctx->config.frameIntervalP > 1)
        avctx->max_b_frames = ctx->config.frameIntervalP - 1;

    nvenc_setup_rate_control(avctx);

    if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) {
        ctx->config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD;
    } else {
        ctx->config.frameFieldMode = NV_ENC_PARAMS_FRAME_FIELD_MODE_FRAME;
    }

    if ((ret = nvenc_setup_codec_config(avctx)) < 0)
        return ret;

    ret = nv->nvEncInitializeEncoder(ctx->nvenc_ctx, &ctx->params);
    if (ret != NV_ENC_SUCCESS) {
        av_log(avctx, AV_LOG_ERROR, "Cannot initialize the decoder");
        return AVERROR_UNKNOWN;
    }

    return 0;
}