From 065f4dceb1e2869e092d3460d042591811839710 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Thu, 7 Apr 2016 23:24:47 +1000 Subject: [PATCH] nvenc: move codec config initialization from the implementation to the base class Supports a better separation of configuration parameters --- sys/nvenc/gstnvbaseenc.c | 135 +++++++++++++++++++++++++++++++--- sys/nvenc/gstnvbaseenc.h | 6 +- sys/nvenc/gstnvh264enc.c | 152 ++++----------------------------------- 3 files changed, 139 insertions(+), 154 deletions(-) diff --git a/sys/nvenc/gstnvbaseenc.c b/sys/nvenc/gstnvbaseenc.c index 53761de482..6efd51414a 100644 --- a/sys/nvenc/gstnvbaseenc.c +++ b/sys/nvenc/gstnvbaseenc.c @@ -969,22 +969,136 @@ gst_nv_base_enc_set_format (GstVideoEncoder * enc, GstVideoCodecState * state) GstNvBaseEnc *nvenc = GST_NV_BASE_ENC (enc); GstVideoInfo *info = &state->info; GstVideoCodecState *old_state = nvenc->input_state; + NV_ENC_RECONFIGURE_PARAMS reconfigure_params = { 0, }; + NV_ENC_INITIALIZE_PARAMS init_params = { 0, }; + NV_ENC_INITIALIZE_PARAMS *params; + NV_ENC_PRESET_CONFIG preset_config = { 0, }; NVENCSTATUS nv_ret; - g_assert (nvenc_class->initialize_encoder); + if (old_state) { + reconfigure_params.version = NV_ENC_RECONFIGURE_PARAMS_VER; + params = &reconfigure_params.reInitEncodeParams; + } else { + params = &init_params; + } + + params->version = NV_ENC_INITIALIZE_PARAMS_VER; + params->encodeGUID = nvenc_class->codec_id; + params->encodeWidth = GST_VIDEO_INFO_WIDTH (info); + params->encodeHeight = GST_VIDEO_INFO_HEIGHT (info); + + { + guint32 n_presets; + GUID *presets; + guint32 i; + + nv_ret = + NvEncGetEncodePresetCount (nvenc->encoder, + params->encodeGUID, &n_presets); + if (nv_ret != NV_ENC_SUCCESS) { + GST_ELEMENT_ERROR (nvenc, LIBRARY, SETTINGS, (NULL), + ("Failed to get encoder presets")); + return FALSE; + } + + presets = g_new0 (GUID, n_presets); + nv_ret = + NvEncGetEncodePresetGUIDs (nvenc->encoder, + params->encodeGUID, presets, n_presets, &n_presets); + if (nv_ret != NV_ENC_SUCCESS) { + GST_ELEMENT_ERROR (nvenc, LIBRARY, SETTINGS, (NULL), + ("Failed to get encoder presets")); + g_free (presets); + return FALSE; + } + + for (i = 0; i < n_presets; i++) { + if (gst_nvenc_cmp_guid (presets[i], nvenc->selected_preset)) + break; + } + g_free (presets); + if (i >= n_presets) { + GST_ELEMENT_ERROR (nvenc, LIBRARY, SETTINGS, (NULL), + ("Selected preset not supported")); + return FALSE; + } + + params->presetGUID = nvenc->selected_preset; + } + + params->enablePTD = 1; + if (!old_state) { + /* this sets the required buffer size and the maximum allowed size on + * subsequent reconfigures */ + /* FIXME: propertise this */ + params->maxEncodeWidth = GST_VIDEO_INFO_WIDTH (info); + params->maxEncodeHeight = GST_VIDEO_INFO_HEIGHT (info); + gst_nv_base_enc_set_max_encode_size (nvenc, params->maxEncodeWidth, + params->maxEncodeHeight); + } else { + guint max_width, max_height; + + gst_nv_base_enc_get_max_encode_size (nvenc, &max_width, &max_height); + + if (GST_VIDEO_INFO_WIDTH (info) > max_width + || GST_VIDEO_INFO_HEIGHT (info) > max_height) { + GST_ELEMENT_ERROR (nvenc, STREAM, FORMAT, ("%s", "Requested stream " + "size is larger than the maximum configured size"), (NULL)); + return FALSE; + } + } + + preset_config.version = NV_ENC_PRESET_CONFIG_VER; + preset_config.presetCfg.version = NV_ENC_CONFIG_VER; + + nv_ret = + NvEncGetEncodePresetConfig (nvenc->encoder, + params->encodeGUID, params->presetGUID, &preset_config); + if (nv_ret != NV_ENC_SUCCESS) { + GST_ELEMENT_ERROR (nvenc, LIBRARY, SETTINGS, (NULL), + ("Failed to get encode preset configuration: %d", nv_ret)); + return FALSE; + } + + if (GST_VIDEO_INFO_IS_INTERLACED (info)) { + if (GST_VIDEO_INFO_INTERLACE_MODE (info) == + GST_VIDEO_INTERLACE_MODE_INTERLEAVED + || GST_VIDEO_INFO_INTERLACE_MODE (info) == + GST_VIDEO_INTERLACE_MODE_MIXED) { + preset_config.presetCfg.frameFieldMode = + NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD; + } + } + + if (info->fps_d > 0 && info->fps_n > 0) { + params->frameRateNum = info->fps_n; + params->frameRateDen = info->fps_d; + } else { + GST_FIXME_OBJECT (nvenc, "variable framerate"); + } + + params->encodeConfig = &preset_config.presetCfg; + + g_assert (nvenc_class->set_encoder_config); + if (!nvenc_class->set_encoder_config (nvenc, state, params->encodeConfig)) { + GST_ERROR_OBJECT (enc, "Subclass failed to set encoder configuration"); + return FALSE; + } G_LOCK (initialization_lock); - if (!nvenc_class->initialize_encoder (nvenc, old_state, state)) { - GST_ERROR_OBJECT (enc, "Subclass failed to reconfigure encoder"); - G_UNLOCK (initialization_lock); - return FALSE; + if (old_state) { + nv_ret = NvEncReconfigureEncoder (nvenc->encoder, &reconfigure_params); + } else { + nv_ret = NvEncInitializeEncoder (nvenc->encoder, params); } G_UNLOCK (initialization_lock); - if (!nvenc->max_encode_width && !nvenc->max_encode_height) { - gst_nv_base_enc_set_max_encode_size (nvenc, GST_VIDEO_INFO_WIDTH (info), - GST_VIDEO_INFO_HEIGHT (info)); + if (nv_ret != NV_ENC_SUCCESS) { + GST_ELEMENT_ERROR (nvenc, LIBRARY, SETTINGS, (NULL), + ("Failed to %sinit encoder: %d", old_state ? "re" : "", nv_ret)); + return FALSE; } + GST_INFO_OBJECT (nvenc, "configured encoder"); if (!old_state) { nvenc->input_info = *info; @@ -1268,9 +1382,8 @@ _map_gl_input_buffer (GstGLContext * context, struct map_gl_input *data) } cuda_ret = - cudaGraphicsResourceGetMappedPointer (&data-> - in_gl_resource->cuda_plane_pointers[i], - &data->in_gl_resource->cuda_num_bytes, + cudaGraphicsResourceGetMappedPointer (&data->in_gl_resource-> + cuda_plane_pointers[i], &data->in_gl_resource->cuda_num_bytes, data->in_gl_resource->cuda_texture); if (cuda_ret != cudaSuccess) { GST_ERROR_OBJECT (data->nvenc, "failed to get mapped pointer of map GL " diff --git a/sys/nvenc/gstnvbaseenc.h b/sys/nvenc/gstnvbaseenc.h index 6debe8eae7..934826b168 100644 --- a/sys/nvenc/gstnvbaseenc.h +++ b/sys/nvenc/gstnvbaseenc.h @@ -104,14 +104,14 @@ typedef struct { GUID codec_id; - gboolean (*initialize_encoder) (GstNvBaseEnc * nvenc, - GstVideoCodecState * old_state, - GstVideoCodecState * state); gboolean (*set_src_caps) (GstNvBaseEnc * nvenc, GstVideoCodecState * state); gboolean (*set_pic_params) (GstNvBaseEnc * nvenc, GstVideoCodecFrame * frame, NV_ENC_PIC_PARAMS * pic_params); + gboolean (*set_encoder_config) (GstNvBaseEnc * nvenc, + GstVideoCodecState * state, + NV_ENC_CONFIG * config); } GstNvBaseEncClass; G_GNUC_INTERNAL diff --git a/sys/nvenc/gstnvh264enc.c b/sys/nvenc/gstnvh264enc.c index 4c7a9846d2..2e60b3da79 100644 --- a/sys/nvenc/gstnvh264enc.c +++ b/sys/nvenc/gstnvh264enc.c @@ -57,8 +57,8 @@ static GstCaps *gst_nv_h264_enc_getcaps (GstVideoEncoder * enc, GstCaps * filter); static gboolean gst_nv_h264_enc_set_src_caps (GstNvBaseEnc * nvenc, GstVideoCodecState * state); -static gboolean gst_nv_h264_enc_initialize_encoder (GstNvBaseEnc * nvenc, - GstVideoCodecState * old_state, GstVideoCodecState * state); +static gboolean gst_nv_h264_enc_set_encoder_config (GstNvBaseEnc * nvenc, + GstVideoCodecState * state, NV_ENC_CONFIG * config); static gboolean gst_nv_h264_enc_set_pic_params (GstNvBaseEnc * nvenc, GstVideoCodecFrame * frame, NV_ENC_PIC_PARAMS * pic_params); static void gst_nv_h264_enc_set_property (GObject * object, guint prop_id, @@ -85,7 +85,7 @@ gst_nv_h264_enc_class_init (GstNvH264EncClass * klass) videoenc_class->getcaps = GST_DEBUG_FUNCPTR (gst_nv_h264_enc_getcaps); nvenc_class->codec_id = NV_ENC_CODEC_H264_GUID; - nvenc_class->initialize_encoder = gst_nv_h264_enc_initialize_encoder; + nvenc_class->set_encoder_config = gst_nv_h264_enc_set_encoder_config; nvenc_class->set_src_caps = gst_nv_h264_enc_set_src_caps; nvenc_class->set_pic_params = gst_nv_h264_enc_set_pic_params; @@ -411,28 +411,14 @@ gst_nv_h264_enc_set_src_caps (GstNvBaseEnc * nvenc, GstVideoCodecState * state) } static gboolean -gst_nv_h264_enc_initialize_encoder (GstNvBaseEnc * nvenc, - GstVideoCodecState * old_state, GstVideoCodecState * state) +gst_nv_h264_enc_set_encoder_config (GstNvBaseEnc * nvenc, + GstVideoCodecState * state, NV_ENC_CONFIG * config) { GstNvH264Enc *h264enc = GST_NV_H264_ENC (nvenc); - NV_ENC_RECONFIGURE_PARAMS reconfigure_params = { 0, }; - NV_ENC_INITIALIZE_PARAMS init_params = { 0, }; - NV_ENC_INITIALIZE_PARAMS *params; - NV_ENC_PRESET_CONFIG preset_config = { 0, }; - NVENCSTATUS nv_ret; - GstVideoInfo *info = &state->info; GstCaps *allowed_caps, *template_caps; GUID selected_profile = NV_ENC_CODEC_PROFILE_AUTOSELECT_GUID; - GUID selected_preset = nvenc->selected_preset; int level_idc = NV_ENC_LEVEL_AUTOSELECT; - - /* TODO: support reconfiguration */ - if (old_state) { - reconfigure_params.version = NV_ENC_RECONFIGURE_PARAMS_VER; - params = &reconfigure_params.reInitEncodeParams; - } else { - params = &init_params; - } + GstVideoInfo *info = &state->info; template_caps = gst_static_pad_template_get_caps (&src_factory); allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (h264enc)); @@ -482,133 +468,19 @@ gst_nv_h264_enc_initialize_encoder (GstNvBaseEnc * nvenc, } gst_caps_unref (template_caps); - params->version = NV_ENC_INITIALIZE_PARAMS_VER; - params->encodeGUID = NV_ENC_CODEC_H264_GUID; - params->encodeWidth = GST_VIDEO_INFO_WIDTH (info); - params->encodeHeight = GST_VIDEO_INFO_HEIGHT (info); - - { - guint32 n_presets; - GUID *presets; - guint32 i; - - nv_ret = - NvEncGetEncodePresetCount (GST_NV_BASE_ENC (h264enc)->encoder, - params->encodeGUID, &n_presets); - if (nv_ret != NV_ENC_SUCCESS) { - GST_ELEMENT_ERROR (h264enc, LIBRARY, SETTINGS, (NULL), - ("Failed to get encoder presets")); - return FALSE; - } - - presets = g_new0 (GUID, n_presets); - nv_ret = - NvEncGetEncodePresetGUIDs (GST_NV_BASE_ENC (h264enc)->encoder, - params->encodeGUID, presets, n_presets, &n_presets); - if (nv_ret != NV_ENC_SUCCESS) { - GST_ELEMENT_ERROR (h264enc, LIBRARY, SETTINGS, (NULL), - ("Failed to get encoder presets")); - g_free (presets); - return FALSE; - } - - for (i = 0; i < n_presets; i++) { - if (gst_nvenc_cmp_guid (presets[i], selected_preset)) - break; - } - g_free (presets); - if (i >= n_presets) { - GST_ELEMENT_ERROR (h264enc, LIBRARY, SETTINGS, (NULL), - ("Selected preset not supported")); - return FALSE; - } - - params->presetGUID = selected_preset; - } - params->enablePTD = 1; - if (!old_state) { - /* this sets the required buffer size and the maximum allowed size on - * subsequent reconfigures */ - /* FIXME: propertise this */ - params->maxEncodeWidth = GST_VIDEO_INFO_WIDTH (info); - params->maxEncodeHeight = GST_VIDEO_INFO_HEIGHT (info); - gst_nv_base_enc_set_max_encode_size (GST_NV_BASE_ENC (h264enc), - params->maxEncodeWidth, params->maxEncodeHeight); - } else { - guint max_width, max_height; - - gst_nv_base_enc_get_max_encode_size (GST_NV_BASE_ENC (h264enc), - &max_width, &max_height); - - if (GST_VIDEO_INFO_WIDTH (info) > max_width - || GST_VIDEO_INFO_HEIGHT (info) > max_height) { - GST_ELEMENT_ERROR (h264enc, STREAM, FORMAT, ("%s", "Requested stream " - "size is larger than the maximum configured size"), (NULL)); - return FALSE; - } - } - - preset_config.version = NV_ENC_PRESET_CONFIG_VER; - preset_config.presetCfg.version = NV_ENC_CONFIG_VER; - - nv_ret = - NvEncGetEncodePresetConfig (GST_NV_BASE_ENC (h264enc)->encoder, - params->encodeGUID, params->presetGUID, &preset_config); - if (nv_ret != NV_ENC_SUCCESS) { - GST_ELEMENT_ERROR (h264enc, LIBRARY, SETTINGS, (NULL), - ("Failed to get encode preset configuration: %d", nv_ret)); - return FALSE; - } - params->encodeConfig = &preset_config.presetCfg; - /* override some defaults */ GST_LOG_OBJECT (h264enc, "setting parameters"); - preset_config.presetCfg.version = NV_ENC_CONFIG_VER; - preset_config.presetCfg.profileGUID = selected_profile; - preset_config.presetCfg.encodeCodecConfig.h264Config.level = level_idc; - preset_config.presetCfg.encodeCodecConfig.h264Config.chromaFormatIDC = 1; + config->profileGUID = selected_profile; + config->encodeCodecConfig.h264Config.level = level_idc; + config->encodeCodecConfig.h264Config.chromaFormatIDC = 1; if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_Y444) { GST_DEBUG_OBJECT (h264enc, "have Y444 input, setting config accordingly"); - preset_config.presetCfg.encodeCodecConfig.h264Config. - separateColourPlaneFlag = 1; - preset_config.presetCfg.encodeCodecConfig.h264Config.chromaFormatIDC = 3; + config->encodeCodecConfig.h264Config.separateColourPlaneFlag = 1; + config->encodeCodecConfig.h264Config.chromaFormatIDC = 3; } /* FIXME: make property */ - preset_config.presetCfg.encodeCodecConfig.h264Config.outputAUD = 1; - - if (GST_VIDEO_INFO_IS_INTERLACED (info)) { - if (GST_VIDEO_INFO_INTERLACE_MODE (info) == - GST_VIDEO_INTERLACE_MODE_INTERLEAVED - || GST_VIDEO_INFO_INTERLACE_MODE (info) == - GST_VIDEO_INTERLACE_MODE_MIXED) { - preset_config.presetCfg.frameFieldMode = - NV_ENC_PARAMS_FRAME_FIELD_MODE_FIELD; - } - } - - if (info->fps_d > 0 && info->fps_n > 0) { - params->frameRateNum = info->fps_n; - params->frameRateDen = info->fps_d; - } else { - GST_FIXME_OBJECT (h264enc, "variable framerate"); - } - - if (old_state) { - nv_ret = - NvEncReconfigureEncoder (GST_NV_BASE_ENC (h264enc)->encoder, - &reconfigure_params); - } else { - nv_ret = - NvEncInitializeEncoder (GST_NV_BASE_ENC (h264enc)->encoder, params); - } - - if (nv_ret != NV_ENC_SUCCESS) { - GST_ELEMENT_ERROR (h264enc, LIBRARY, SETTINGS, (NULL), - ("Failed to %sinit encoder: %d", old_state ? "re" : "", nv_ret)); - return FALSE; - } - GST_INFO_OBJECT (h264enc, "configured encoder"); + config->encodeCodecConfig.h264Config.outputAUD = 1; return TRUE; }