gpt4 book ai didi

c++ - 如何将帧从 OpenCV C++ 代码流式传输到 Video4Linux 或 ffmpeg?

转载 作者:行者123 更新时间:2023-12-04 22:56:39 25 4
gpt4 key购买 nike

我正在尝试使用 OpenCV 来处理来自视频流的帧。目标是从流中获取帧,对其进行处理,然后将处理后的帧放入新的/新鲜的流中。
我已经能够使用 OpenCV 视频捕获功能成功读取流。但不知道如何使用已处理的帧创建输出流。
为了进行一些基本测试,我使用 ffmpeg 从本地视频文件创建了一个流,如下所示:

ffmpeg -i sample.mp4 -v 0 -vcodec mpeg4 -f mpegts \
"udp://@127.0.0.1:23000?overrun_nonfatal=1&fifo_size=50000000"
在我使用 OpenCV 库的 VideoCapture 功能的 C++ 代码中,我能够捕获上面创建的流。下面附上了我要实现的基本布局:
cv::VideoCapture capture("udp://@127.0.0.1:23000?overrun_nonfatal=1&fifo_size=50000000", cv::CAP_FFMPEG);

cv::Mat frame;

while (true)
{
// use the above stream to capture a frame
capture >> frame;

// process the frame (not relevant here)
...

// finally, after all the processing is done I
// want to put this frame on a new stream say at
// udp://@127.0.0.1:25000, I don't know how to do
// this, ideally would like to use Video4Linux but
// solutions with ffmpeg are appreciated as well
}
正如您从上面代码中的评论中看到的那样,我什至不知道应该如何开始处理这个问题,我尝试搜索类似的问题,但我能找到的只是如何使用流进行 VideoCapture,与输出到溪流。
我对此比较陌生,对你们中的许多人来说,这似乎是一个非常基本的问题,请原谅。

最佳答案

我们可以使用与我的 following Python code sample 中相同的技术。 .

  • 将FFmpeg作为子进程执行,打开stdin管道进行写入
     FILE *pipeout = popen(ffmpeg_cmd.c_str(), "w")
  • frame.data到 FFmpeg 子进程的标准输入管道(在循环中)
     fwrite(frame.data, 1, width*height*3, pipeout);
  • 最后关闭管道(它将关闭子进程)
     pclose(pipeout);

  • 以下示例是一个通用示例 - 构建编号帧,并将编码视频写入 MKV 输出文件。
    该示例使用以下等效命令行: ffmpeg -y -f rawvideo -r 10 -video_size 320x240 -pixel_format bgr24 -i pipe: -vcodec libx264 -crf 24 -pix_fmt yuv420p output.mkv您可以根据您的特定要求调整参数(将 output.mkv 替换为 udp://@127.0.0.1:25000 )。
    capture >> frame 替换编号的框架,并调整大小和帧率。

    代码示例:
    #include <stdio.h>
    #include <chrono>
    #include <thread>
    #include "opencv2/opencv.hpp"

    int main()
    {
    int width = 320;
    int height = 240;
    int n_frames = 100;
    int fps = 10;

    //Use a "generic" example (write the output video in output.mkv video file).
    //ffmpeg -y -f rawvideo -r 10 -video_size 320x240 -pixel_format bgr24 -i pipe: -vcodec libx264 -crf 24 -pix_fmt yuv420p output.mkv
    std::string ffmpeg_cmd = std::string("ffmpeg -y -f rawvideo -r ") + std::to_string(fps) +
    " -video_size " + std::to_string(width) + "x" + std::to_string(height) +
    " -pixel_format bgr24 -i pipe: -vcodec libx264 -crf 24 -pix_fmt yuv420p output.mkv";

    //Execute FFmpeg as sub-process, open stdin pipe (of FFmpeg sub-process) for writing.
    //In Windows we need to use _popen and in Linux popen
    #ifdef _MSC_VER
    FILE *pipeout = _popen(ffmpeg_cmd.c_str(), "wb"); //Windows (ffmpeg.exe must be in the execution path)
    #else
    //https://batchloaf.wordpress.com/2017/02/12/a-simple-way-to-read-and-write-audio-and-video-files-in-c-using-ffmpeg-part-2-video/
    FILE *pipeout = popen(ffmpeg_cmd.c_str(), "w"); //Linux (assume ffmpeg exist in /usr/bin/ffmpeg (and in path).
    #endif

    for (int i = 0; i < n_frames; i++)
    {
    cv::Mat frame = cv::Mat(height, width, CV_8UC3);
    frame = cv::Scalar(60, 60, 60); //Fill background with dark gray
    cv::putText(frame, std::to_string(i+1), cv::Point(width/2-50*(int)(std::to_string(i+1).length()), height/2+50), cv::FONT_HERSHEY_DUPLEX, 5, cv::Scalar(30, 255, 30), 10); // Draw a green number

    cv::imshow("frame", frame);cv::waitKey(1); //Show the frame for testing

    //Write width*height*3 bytes to stdin pipe of FFmpeg sub-process (assume frame data is continuous in the RAM).
    fwrite(frame.data, 1, width*height*3, pipeout);
    }

    // Flush and close input and output pipes
    fflush(pipeout);

    #ifdef _MSC_VER
    _pclose(pipeout); //Windows
    #else
    pclose(pipeout); //Linux
    #endif

    //It looks like we need to wait one more second at the end. //https://stackoverflow.com/a/62804585/4926757
    std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // sleep for 1 second

    return 0;
    }

    关于c++ - 如何将帧从 OpenCV C++ 代码流式传输到 Video4Linux 或 ffmpeg?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72884815/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com