Hello. We are streaming h264 compressed video (1080p, 30fps) from PX2. We are using two configurations, please see the table below.
Configuration # | Encoder | Decoder | Latency
----------------------------------------------------------------------------------------
1 | gstreamer(nvmediah264videnc) | gstreamer(vaapidecode) | 90ms
2 | nvmedia API | gstreamer(vaapidecode) | 160ms
We would like to configure encoding process with nvmedia API (configuration #2) to reduce the latency as much as possible. Down below is our code for creating and configuring the encoder.
void Encoder::CreateEncoder() noexcept
{
NVM_SURF_FMT_DEFINE_ATTR(surfaceFormatAttributes);
NVM_SURF_FMT_SET_ATTR_YUV(
surfaceFormatAttributes, YUV, 420, SEMI_PLANAR, UINT, 8, BL);
NvMediaSurfaceType surfaceType = NvMediaSurfaceFormatGetType(
surfaceFormatAttributes, NVM_SURF_FMT_ATTR_MAX);
if (surfaceType == NvMediaSurfaceType_Unsupported)
ERROR("NvMediaSurfaceFormatGetType() failed");
NvMediaSurfAllocAttr surfAllocAttrs[] = {
{ NVM_SURF_ATTR_WIDTH, mWidth },
{ NVM_SURF_ATTR_HEIGHT, mHeight },
{ NVM_SURF_ATTR_CPU_ACCESS, NVM_SURF_ATTR_CPU_ACCESS_UNCACHED }
};
const int numSurfAllocAttrs =
sizeof(surfAllocAttrs) / sizeof(surfAllocAttrs[0]);
DEBUG("Creating video surface ...");
mVideoSurface = std::shared_ptr<NvMediaVideoSurface>(
NvMediaVideoSurfaceCreateNew(
mDevice.get(), surfaceType, surfAllocAttrs, numSurfAllocAttrs, 0
),
[] (NvMediaVideoSurface * surface) {
if (surface != nullptr)
{
DEBUG("Destroying video surface ...");
NvMediaVideoSurfaceDestroy(surface);
}
});
if (!mVideoSurface)
ERROR("NvMediaVideoSurfaceCreateNew() failed");
NvMediaEncodeInitializeParamsH264 params;
std::memset(¶ms, 0, sizeof(NvMediaEncodeInitializeParamsH264));
params.encodeHeight = mHeight;
params.encodeWidth = mWidth;
params.enableLimitedRGB = 0;
params.frameRateNum = 30;
params.frameRateDen = 1;
params.profile = NVMEDIA_ENCODE_PROFILE_BASELINE;
params.level = NVMEDIA_ENCODE_LEVEL_H264_42;
params.maxNumRefFrames = 1;
params.enableExternalMEHints = NVMEDIA_FALSE;
params.enableSliceEncode = NVMEDIA_TRUE;
DEBUG("Creating encoder ...");
mEncoder = std::shared_ptr<NvMediaVideoEncoder>(
NvMediaVideoEncoderCreate(
mDevice.get(),
NVMEDIA_VIDEO_ENCODE_CODEC_H264,
¶ms,
surfaceType,
0,
2,
NVMEDIA_ENCODER_INSTANCE_AUTO),
[] (NvMediaVideoEncoder * encoder) {
if (encoder != nullptr)
{
DEBUG("Destroying encoder ...");
NvMediaVideoEncoderDestroy(encoder);
}
});
if (!mEncoder)
ERROR("NvMediaVideoEncoderCreate() failed");
NvMediaEncodeConfigH264VUIParams vuiParams;
std::memset(&vuiParams, 0, sizeof(NvMediaEncodeConfigH264VUIParams));
NvMediaEncodeRCParams rcParams;
std::memset(&rcParams, 0, sizeof(NvMediaEncodeRCParams));
rcParams.numBFrames = 0;
rcParams.rateControlMode = NVMEDIA_ENCODE_PARAMS_RC_VBR;
rcParams.params.vbr.averageBitRate = BITRATE;
rcParams.params.vbr.maxBitRate = BITRATE * 2u;
NvMediaEncodeConfigH264 config;
std::memset(&config, 0, sizeof(NvMediaEncodeConfigH264));
config.gopLength = 15;
config.rcParams = rcParams;
config.idrPeriod = 0;
config.h264VUIParameters = &vuiParams;
config.quality = NVMEDIA_ENCODE_QUALITY_L0;
config.features =
NVMEDIA_ENCODE_CONFIG_H264_ENABLE_RTP_MODE_OUTPUT |
NVMEDIA_ENCODE_CONFIG_H264_ENABLE_SLICE_LEVEL_OUTPUT |
NVMEDIA_ENCODE_CONFIG_H264_ENABLE_INTRA_REFRESH;
config.bdirectMode = NVMEDIA_ENCODE_H264_BDIRECT_MODE_DISABLE;
config.pocType = NVMEDIA_ENCODE_H264_POC_TYPE_0;
config.adaptiveTransformMode =
NVMEDIA_ENCODE_H264_ADAPTIVE_TRANSFORM_DISABLE;
config.intraRefreshCnt = 5;
config.intraRefreshPeriod = 15;
DEBUG("Setting encoder configuration ...");
NvMediaStatus status = NvMediaVideoEncoderSetConfiguration(
mEncoder.get(), &config);
if (status != NVMEDIA_STATUS_OK)
ERROR("NvMediaVideoEncoderSetConfiguration() failed");
}
SDK in use is 5.0.5.0b. Please advise.