OpenCV 检查机器上是否安装了视频编解码器 (C++)

OpenCV checking if video-codec is installed on machine (C++)

问题:

我想实现一个安全版本以通过 OpenCV 将数据处理成视频,这应该适用于 Windows、Mac 和 Linux。数据必须保存在无损视频编解码器中。


在我目前的设置下保存文件完全没有问题,而且我知道使用-1 as fourcc with videoWriter 会弹出一个window。 我不能保证的是系统完全有能力显示 window !所以弹出菜单可以作为后备方案,但不是主要解决方案。


问题:

有没有办法检查 OpenCV 是否在机器上安装了特定的视频编解码器而没有 运行 编译问题?类似于:

if (`codec installed`)
    int codec = opencvfourcc(codec)
else
    int codec = -1

OpenCV 使用 FFmpeg 解码视频文件。因此,如果 OpenCV 已在系统上使用 FFmpeg 版本构建,那么我们可以使用 FFmpeg 命令行来检查我们选择的编解码器的可用性。对于来自 C++ 的 运行 系统命令,我使用了来自 here. This post 的代码详细说明了如何检查 OS 类型。

#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>

#if defined(_WIN32) || defined(_WIN64)
#define OS_WINDOWS
#elif defined(__APPLE__) || defined(__MACH__)
#define OS_OSX
#elif defined(__linux__)
#define OS_LINUX
#endif

std::string exec(const std::string& command ) {
    const char* cmd = command.c_str();
    std::array<char, 128> buffer;
    std::string result;

    #if defined(OS_WINDOWS)
    std::shared_ptr<FILE> pipe(_popen(cmd, "r"), _pclose);
    #elif defined(OS_LINUX) || defined (OS_OSX)
    std::shared_ptr<FILE> pipe(popen(cmd, "r"), pclose);
    #endif

    if (!pipe) throw std::runtime_error("popen() failed!");
    while (!feof(pipe.get())) {
        if (fgets(buffer.data(), 128, pipe.get()) != nullptr)
            result += buffer.data();
    }
    return result;
}

int main() {

  // codec of choice
  std::string codec = "H264";

  // if OS is linux or OSX then use FFmpeg with grep command
  #if defined (OS_LINUX) || defined (OS_OSX)
  std::string command = "ffmpeg -codecs | grep -i ";
  // if WINDOWS then FFmpeg with findstr
  #elif defined (OS_WINDOWS)
  std::string command = "ffmpeg -codecs | findstr /i ";
  #endif

  // execute the system command and get the output
  std::string str = exec(command+codec);

  // if the output string contains the letters DEV then FFmpeg supports the codec
  // D: Decoding supported
  // E: Encoding supported
  // V: Video codec
  std::size_t found = str.find("DEV");

  if(found != std::string::npos)
    std::cout<<"Codec Found"<<std::endl;

return 0;
}