在深度学习处理视频过程中,通常是先解码视频获取视频帧并转为cv::Mat后进行处理。本章介绍如何将处理后的图片使用GPU编码为视频码流并封装为MP4格式。

开发硬件:I7-9750H GTX1660ti

操作系统:Ubuntu16.04

驱动版本:440显卡驱动,cuda10.2,video_codec_sdk_8.2.15

一般会在处理后的图片上叠加结果信息

GPU编码基于NVIDIA Video_Codec_SDK中的AppEncode\AppEncLowLatency\AppEncLowLatency.cpp实现。

关键代码部分如下:

    encodeConfig.gopLength = NVENC_INFINITE_GOPLENGTH;
    encodeConfig.frameIntervalP = 1;
    if (pEncodeCLIOptions->IsCodecH264())
    {
        encodeConfig.encodeCodecConfig.h264Config.idrPeriod = NVENC_INFINITE_GOPLENGTH;
    }
    else
    {
        encodeConfig.encodeCodecConfig.hevcConfig.idrPeriod = NVENC_INFINITE_GOPLENGTH;
    }

    encodeConfig.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CBR_LOWDELAY_HQ;
    encodeConfig.rcParams.averageBitRate = (static_cast<unsigned int>(5.0f * initializeParams.encodeWidth * initializeParams.encodeHeight) / (1280 * 720)) * 100000;
    encodeConfig.rcParams.vbvBufferSize = (encodeConfig.rcParams.averageBitRate * initializeParams.frameRateDen / initializeParams.frameRateNum) * 5;
    encodeConfig.rcParams.maxBitRate = encodeConfig.rcParams.averageBitRate;
    encodeConfig.rcParams.vbvInitialDelay = encodeConfig.rcParams.vbvBufferSize;

gopLength为关键帧间隔,默认是NVENC_INFINITE_GOPLENGTH  0xffffffff,相当于无限大只有一个关键帧,在推流等很多应用场景下很容易出现问题。推荐设置为25/50等。

averageBitRate为编码码率,如果是长时间保存视频,推荐将码率设低,推荐4000~8000kbps。

当成功对图片数据编码后,第一次的编码返回的是sps,pps信息,无论是封装视频文件还是推流均需要该信息。

从第二次开始返回视频码流。

如果直接将sps、pps和后续的视频码流保存为二进制文件,可以用ubuntu的默认视频播放软件打开,但是其余播放软件如vlc、potplayer等均无法打开,浏览器也不能直接预览。

可以使用libmp4v2将硬编码后的数据直接进行封装保存为视频文件。

可以参照https://blog.csdn.net/firehood_/article/details/8813587文中示例,将码流直接封装为MP4文件,封装后的MP4文件可以直接在web端播放。

如果在录制视频时,需要分时录制封装多段视频,则需要在一开始将sps、pps信息保存下来,每次重新开始录制并封装MP4时,先将sps、pps信息写入文件头部,再写入视频帧数据。

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐