ffmpeg GPU加速 c++ Mat 转 h264
时间: 2023-12-31 09:04:54 浏览: 47
要使用 ffmpeg 进行 GPU 加速的 H.264 编码,需要使用 NVIDIA 的 CUDA 库来加速编码过程。同时,也需要使用 OpenCV 库来进行图像处理和转换。
下面是一个示例代码,演示了如何使用 OpenCV 和 ffmpeg 进行 GPU 加速的 H.264 编码。
```c++
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/cuda.hpp>
#include <opencv2/cudaarithm.hpp>
#include <opencv2/cudaimgproc.hpp>
#include <opencv2/cudacodec.hpp>
#include <opencv2/highgui/highgui.hpp>
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
}
using namespace std;
using namespace cv;
int main()
{
// Initialize CUDA
cv::cuda::setDevice(0);
// Open the video capture device
VideoCapture cap(0);
// Check if the capture device was successfully opened
if (!cap.isOpened())
{
cerr << "Failed to open capture device" << endl;
return -1;
}
// Get the default CUDA H.264 encoder
Ptr<cv::cudacodec::Encoder> encoder = cv::cudacodec::createEncoder(cv::cudacodec::Codec::H264);
// Set the H.264 encoder parameters
encoder->setBitrate(1000000);
encoder->setFrameRate(30);
encoder->setWidth(cap.get(CAP_PROP_FRAME_WIDTH));
encoder->setHeight(cap.get(CAP_PROP_FRAME_HEIGHT));
// Allocate a temporary buffer for the encoded data
cuda::GpuMat temp;
temp.create(encoder->getOutputBufferSize());
// Open the output file
AVFormatContext* formatContext = avformat_alloc_context();
int err = avformat_alloc_output_context2(&formatContext, NULL, NULL, "output.mp4");
if (err < 0)
{
cerr << "Failed to initialize output format" << endl;
return -1;
}
AVOutputFormat* outputFormat = formatContext->oformat;
AVCodec* codec = avcodec_find_encoder(outputFormat->video_codec);
if (!codec)
{
cerr << "Failed to find codec" << endl;
return -1;
}
AVStream* stream = avformat_new_stream(formatContext, codec);
if (!stream)
{
cerr << "Failed to allocate stream" << endl;
return -1;
}
AVCodecContext* codecContext = avcodec_alloc_context3(codec);
if (!codecContext)
{
cerr << "Failed to allocate codec context" << endl;
return -1;
}
codecContext->codec_tag = 0;
codecContext->width = encoder->getWidth();
codecContext->height = encoder->getHeight();
codecContext->time_base = { 1, encoder->getFrameRate() };
codecContext->pix_fmt = AV_PIX_FMT_YUV420P;
if (formatContext->oformat->flags & AVFMT_GLOBALHEADER)
{
codecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
err = avcodec_open2(codecContext, codec, NULL);
if (err < 0)
{
cerr << "Failed to open codec" << endl;
return -1;
}
err = avcodec_parameters_from_context(stream->codecpar, codecContext);
if (err < 0)
{
cerr << "Failed to copy codec parameters" << endl;
return -1;
}
av_dump_format(formatContext, 0, "output.mp4", 1);
err = avio_open(&formatContext->pb, "output.mp4", AVIO_FLAG_WRITE);
if (err < 0)
{
cerr << "Failed to open output file" << endl;
return -1;
}
err = avformat_write_header(formatContext, NULL);
if (err < 0)
{
cerr << "Failed to write header" << endl;
return -1;
}
// Loop over the video frames
Mat frame;
while (true)
{
// Capture a new frame from the video device
cap >> frame;
if (frame.empty())
{
break;
}
// Convert the frame to YUV420P format
cuda::GpuMat gpuFrame, gpuYUV;
gpuFrame.upload(frame);
cuda::cvtColor(gpuFrame, gpuYUV, COLOR_BGR2YUV_I420);
// Encode the frame
encoder->encode(gpuYUV, temp);
// Write the encoded frame to the output file
AVPacket packet;
av_init_packet(&packet);
packet.data = temp.ptr();
packet.size = (int)temp.cols;
packet.pts = av_rescale_q(encoder->getEncodedFrames(), { 1, encoder->getFrameRate() }, codecContext->time_base);
packet.dts = packet.pts;
packet.duration = av_rescale_q(1, { 1, encoder->getFrameRate() }, codecContext->time_base);
packet.stream_index = stream->index;
err = av_interleaved_write_frame(formatContext, &packet);
if (err < 0)
{
cerr << "Failed to write frame" << endl;
return -1;
}
}
// Release resources
av_write_trailer(formatContext);
avcodec_close(codecContext);
avcodec_free_context(&codecContext);
avformat_close_input(&formatContext);
return 0;
}
```
这个示例代码使用 OpenCV 和 ffmpeg 库进行 GPU 加速的 H.264 编码。它首先创建了一个 CUDA H.264 编码器,然后使用它来编码从摄像头捕获的视频帧。编码后的数据存储在一个临时的 GPU 内存区域中,然后写入输出文件。最后,释放所有的资源。
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)