如何将NVIDIA GPU编码的视频保存到.avi / .mp4容器中?

时间:2019-05-22 10:30:28

标签: c++ nvidia video-encoding video-codecs

一段时间以来,我一直在使用NVidia视频编解码器库,并且能够从摄像机读取帧并将其馈送到编码器。编码文件正在保存。所以这是我需要帮助的相关代码。

最初,我打开编码数据的输出文件,如下所示。 szOutFilePath包含用于存储视频编码文件的路径和文件名。

示例: szOutFilePath =“ /home/admin/project/video.avi”

//Encoder output file
    std::ofstream fpOut(szOutFilePath, std::ios::out | std::ios::binary | std::ofstream::trunc);
    if (!fpOut)
    {

        std::ostringstream err;
        err << "Unable to open output file: " << szOutFilePath << std::endl;
        throw std::invalid_argument(err.str());
    }

然后我将相机捕获的opencv图像转换为YUV图像。

 openCvImage= cv::Mat(ptrGrabResult->GetHeight(), ptrGrabResult->GetWidth(), CV_8UC3, (uint8_t *) pylonImage.GetBuffer());
 //Converting the opencv image to YUV420 format. 
 cvtColor(openCvImage, yuvImage, CV_BGR2YUV_I420);

包含当前图像帧的yuvImage如下馈送到编码器。

 try
   {
    // For receiving encoded packets
    std::vector<std::vector<uint8_t>> vPacket;
    if (counter != c_countOfImagesToGrab)
       {
           const NvEncInputFrame* encoderInputFrame = enc.GetNextInputFrame();

           NvEncoderCuda::CopyToDeviceFrame(cuContext, (uint8_t*)yuvImage.data, 0, (CUdeviceptr)encoderInputFrame->inputPtr,
                                                     (int)encoderInputFrame->pitch,
                                                     enc.GetEncodeWidth(),
                                                     enc.GetEncodeHeight(),
                                                     CU_MEMORYTYPE_HOST,
                                                     encoderInputFrame->bufferFormat,
                                                     encoderInputFrame->chromaOffsets,
                                                     encoderInputFrame->numChromaPlanes);
                    enc.EncodeFrame(vPacket);

        }
     else
        {
            enc.EndEncode(vPacket);
        }

        nFrame += (int)vPacket.size();
         for (std::vector<uint8_t> &packet : vPacket)
             {
              // For each encoded packet

                 fpOut.write(reinterpret_cast<char*>(packet.data()), packet.size());
              }


    }

     catch (const std::exception &ex)
         {

             std::cout << ex.what();

          }

我正在获取正确的编码视频文件。有趣的是,该视频正在名为“ Parole Media Player”的媒体播放器中正常播放。但是,同一视频不能在VLC媒体播放器中播放。我的猜测是,h264编码的数据没有正确格式化并放入.avi容器中,结果VLC媒体播放器无法播放它。

谁能告诉我如何使用NVidia视频编解码器库正确创建容器。我一直在寻找解决方案很长时间,但是失败了。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

只需回答我自己的问题,我就将编码后的视频保存为.264格式,并使用ffmpeg库将其转换为.MP4​​格式。感谢“评论”部分的人清除我的疑问。你们都是MVP。