static int nvenc_alloc_surface(AVCodecContext *avctx, int idx) { NVENCContext *ctx = avctx->priv_data; NV_ENCODE_API_FUNCTION_LIST *nv = &ctx->nvel.nvenc_funcs; int ret; NV_ENC_CREATE_INPUT_BUFFER in_buffer = { 0 }; NV_ENC_CREATE_BITSTREAM_BUFFER out_buffer = { 0 }; in_buffer.version = NV_ENC_CREATE_INPUT_BUFFER_VER; out_buffer.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER; in_buffer.width = avctx->width; in_buffer.height = avctx->height; in_buffer.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_UNCACHED; switch (avctx->pix_fmt) { case AV_PIX_FMT_YUV420P: in_buffer.bufferFmt = NV_ENC_BUFFER_FORMAT_YV12_PL; break; case AV_PIX_FMT_NV12: in_buffer.bufferFmt = NV_ENC_BUFFER_FORMAT_NV12_PL; break; case AV_PIX_FMT_YUV444P: in_buffer.bufferFmt = NV_ENC_BUFFER_FORMAT_YUV444_PL; break; default: return AVERROR_BUG; } ret = nv->nvEncCreateInputBuffer(ctx->nvenc_ctx, &in_buffer); if (ret != NV_ENC_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "CreateInputBuffer failed\n"); return AVERROR_UNKNOWN; } ctx->in[idx].in = in_buffer.inputBuffer; ctx->in[idx].format = in_buffer.bufferFmt; /* 1MB is large enough to hold most output frames. * NVENC increases this automaticaly if it's not enough. */ out_buffer.size = BITSTREAM_BUFFER_SIZE; out_buffer.memoryHeap = NV_ENC_MEMORY_HEAP_SYSMEM_UNCACHED; ret = nv->nvEncCreateBitstreamBuffer(ctx->nvenc_ctx, &out_buffer); if (ret != NV_ENC_SUCCESS) { av_log(avctx, AV_LOG_ERROR, "CreateBitstreamBuffer failed\n"); return AVERROR_UNKNOWN; } ctx->out[idx].out = out_buffer.bitstreamBuffer; ctx->out[idx].busy = 0; return 0; }
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(¶ms, 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(¶ms, &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, ¶ms); } { 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); } }