FFMPEG 动态库编译(GPU)
-
下载FFMPEG源码
https://ffmpeg.org/
,这里选择的是ffmpeg-4.3.1.tar.bz2 -
下载nvenc的头文件
git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git cd nv-codec-headers make sudo make install export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig"
注意选择对应cuda的版本
-
编译
./configure --prefix=/yourpath/install --disable-x86asm --enable-shared --disable-static \ --enable-cuda --enable-cuvid --enable-nvenc --enable-nonfree \ --enable-libnpp --extra-cflags=-I/usr/local/cuda/include \ --extra-ldflags=-L/usr/local/cuda/lib64
-
验证,终端输入ffmpeg
ffmpeg version 4.3.1 Copyright (c) 2000-2020 the FFmpeg developers built with gcc 7 (Ubuntu 7.5.0-3ubuntu1~18.04) configuration: --enable-shared --enable-cuda --enable-cuvid --enable-nvenc --enable-nonfree --enable-libnpp --extra-cflags=-I/usr/local/cuda/include --extra-ldflags=-L/usr/local/cuda/lib64 libavutil 56. 51.100 / 56. 51.100 libavcodec 58. 91.100 / 58. 91.100 libavformat 58. 45.100 / 58. 45.100 libavdevice 58. 10.100 / 58. 10.100 libavfilter 7. 85.100 / 7. 85.100 libswscale 5. 7.100 / 5. 7.100 libswresample 3. 7.100 / 3. 7.100 Hyper fast Audio and Video encoder usage: ffmpeg [options] [[infile options] -i infile]... { [outfile options] outfile}... Use -h to get full help or, even better, run 'man ffmpeg'
ffmpeg -hwaccels
打开 ld.so.conf添加 /usr/local/lib(ffmpeg安装库目录)
sudo gedit /etc/ld.so.conf ------------------------------------------- include /etc/ld.so.conf.d/*.conf 添加ffmpeg的路径 /usr/local/lib ------------------------------------------- sudo ldconfig
硬解流图
同时支持软解和硬解,软解将HWDeviceName设置为gpu即可,即: std::string HWDeviceName = “cpu”;
文件目录
├── 3rdparty
│ ├── FreeSerif
│ ├── ffmpeg
│ │ ├── include
│ │ │ ├── libavcodec
│ │ │ ├── libavdevice
│ │ │ ├── libavfilter
│ │ │ ├── libavformat
│ │ │ ├── libavutil
│ │ │ ├── libswresample
│ │ │ └── libswscale
│ │ └── lib
│ ├── opencv
│ └── spd
│ └── spdlog
│ ├── cfg
│ ├── details
│ ├── fmt
│ │ └── bundled
│ └── sinks
├── CMakeLists.txt
├── README.md
├── build
├── docs
│ ├── imgs
│ │ └── spdlog.png
│ └── spdlog.md
├── incs
│ ├── CGDesktopCatch.hpp
│ ├── CGFFNvDecode.hpp
│ ├── CGUsbCamera.hpp
│ ├── common.hpp
│ └── mylog.hpp
├── srcs
│ ├── CGDesktopCatch.cpp
│ ├── CGFFNvDecode.cpp
│ └── CGUsbCamera.cpp
└── test
├── CGDesktopCatchDemo.cpp
├── CMakeLists.txt
├── FFNvDecode.cpp
├── UsbCameraDemo.cpp
├── demo.cpp
└── spddemo.cpp
CGFFNvDecode.hpp
#pragma once
#include "common.hpp"
#include <iostream>
#include <memory>
#include <string>
#include <thread>
class CGFFNvDecode
{
public:
AVFormatContext *m_inputAVFormatCxt = nullptr;
AVFormatContext *m_outputAVFormatCxt = nullptr;
AVCodecContext *decoderCtx = nullptr;
AVStream *videoStream = nullptr;
AVCodec *decoder = nullptr;
int m_VideoStreamIdx;
std::thread m_hThread;
public:
CGFFNvDecode(int chan);
~CGFFNvDecode();
void SetInputUrl(std::string rtspUrl);
void SetOutputPath(std::string ofilename);
void StartDecode();
void StopDecode();
void closeOutputStream();
private:
int decChan;
int64_t pts_v[2] = {
0};
int64_t dts_v[2] = {
0};
int64_t packetCount = 0;
int64_t frameCount = 0;
bool m_bUseHWDecode{
true};
bool m_bStoped{
true};
bool m_bInputInited{
false};
bool m_bOutputInited{
false};
bool m_bAddFilter{
true};
std::string HWDeviceName = "cuda";
std::string m_inputUrl;
std::string m_outputFile;
AVBufferRef *hw_device_ctx = nullptr;
enum AVPixelFormat hwPixFmt;
enum AVHWDeviceType hwDeviceType;
std::shared_ptr<std::mutex> ctxLock = std::make_shared<std::mutex>();
private:
void Init();
int GetHWDeviceByName(std::string deviceName);
void run();
void ReadingThrd(void *pParam);
int OpenInput(std::string inputUrl);
int openOutputStream();
int GetHwPixFormat();
int InitHWdecoder(AVCodecContext *ctx, const enum AVHWDeviceType type);
int GetDecodeResult(AVFrame *frame);
std::shared_ptr<AVPacket> ReadPacketFromSource();
std::shared_ptr<AVFrame> ReadFrameFromDecoder(AVPacket *pkt);
int WritePacket(std::shared_ptr<AVPacket> packet);
void Decoding();
void CloseInput();
void AddFilterToFrame(AVFrame *pSrcFrame, AVFrame *pDestFrame, int x, int y, int w, int h);
};
CGFFNvDecode.cpp
#include "CGFFNvDecode.hpp"
#include "opencv2/opencv.hpp"
#include <exception>
#include <iostream>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <thread>
using namespace std;
static string AvErrToStr(int avErrCode)
{
const auto bufSize = 1024U;
char *errString = (char *) calloc(bufSize, sizeof(*errString));
if (!errString)
{
return string();
}
if (0 != av_strerror(avErrCode, errString, bufSize - 1))
{
free(errString);
stringstream ss;
ss << "Unknown error with code " << avErrCode;
return ss.str();
}
string str(errString);
free(errString);
return str;
}
static enum AVPixelFormat GetHwFormat(AVCodecContext *ctx, const enum AVPixelFormat *pixFmts)
{
const enum AVPixelFormat *p;
for (p = pixFmts; *p != -1; p++)
{
if (*p == AV_PIX_FMT_CUDA)
{
return *p;
}
}
LOG_ERROR("Failed to get HW surface format");
return AV_PIX_FMT_NONE;
}
CGFFNvDecode::CGFFNvDecode(int chan)
{
this->decChan = chan;
this->Init();
}
CGFFNvDecode::~CGFFNvDecode() {
}
int CGFFNvDecode::GetHWDeviceByName(std::string deviceName)
{
hwDeviceType = av_hwdevice_find_type_by_name(deviceName.c_str());
if (hwDeviceType == AV_HWDEVICE_TYPE_NONE
版权声明:本文为xxboy61原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。