avcodec_receive_frame 后构建Mat 怎么传参
时间: 2024-01-25 08:01:46 浏览: 154
avcodec_receive_frame 函数返回的是AVFrame类型的指针,需要将其转换为OpenCV中的Mat类型。可以通过以下代码将AVFrame转换为Mat:
```c++
AVFrame* frame; // 假设已经接收到一个视频帧
// 将AVFrame转换为Mat
cv::Mat mat(frame->height, frame->width, CV_8UC3, frame->data[0], frame->linesize[0]);
```
其中,AVFrame中的 data[0] 表示帧数据存储的指针,linesize[0] 表示每行数据的字节数。CV_8UC3 表示Mat的数据类型为8位无符号整数,通道数为3。
接下来就可以将Mat作为参数传递给其他函数进行处理了。
相关问题
cv::mat转码h265存入另一个cv::mat
要将一个cv::Mat转码为H265并存入另一个cv::Mat,你可以使用FFmpeg库进行编码和解码。以下是一个示例代码:
```cpp
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
}
cv::Mat cvMatToH265(cv::Mat& frame) {
cv::Mat h265Frame;
AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H265);
if (!codec) {
// 处理无法找到编码器的情况
return h265Frame;
}
AVCodecContext* codecContext = avcodec_alloc_context3(codec);
if (!codecContext) {
// 处理无法分配编码器上下文的情况
return h265Frame;
}
// 设置编码器参数
codecContext->width = frame.cols;
codecContext->height = frame.rows;
codecContext->pix_fmt = AV_PIX_FMT_YUV420P;
codecContext->time_base = {1, 30};
// 打开编码器
if (avcodec_open2(codecContext, codec, nullptr) < 0) {
// 处理无法打开编码器的情况
avcodec_free_context(&codecContext);
return h265Frame;
}
// 创建AVFrame用于保存转换后的图像数据
AVFrame* avFrame = av_frame_alloc();
avFrame->format = codecContext->pix_fmt;
avFrame->width = frame.cols;
avFrame->height = frame.rows;
// 分配图像数据缓冲区
int bufferSize = av_image_get_buffer_size(codecContext->pix_fmt, frame.cols, frame.rows, 1);
uint8_t* buffer = (uint8_t*)av_malloc(bufferSize);
av_image_fill_arrays(avFrame->data, avFrame->linesize, buffer, codecContext->pix_fmt, frame.cols, frame.rows, 1);
// 将cv::Mat转换为AVFrame并编码为H265
cv::Mat yuvFrame;
cv::cvtColor(frame, yuvFrame, cv::COLOR_BGR2YUV_I420);
avFrame->data[0] = yuvFrame.data;
avFrame->data[1] = yuvFrame.data + frame.cols * frame.rows;
avFrame->data[2] = yuvFrame.data + frame.cols * frame.rows * 5 / 4;
AVPacket packet;
av_init_packet(&packet);
packet.data = nullptr;
packet.size = 0;
int ret = avcodec_send_frame(codecContext, avFrame);
if (ret < 0) {
// 处理发送帧数据失败的情况
av_frame_free(&avFrame);
avcodec_free_context(&codecContext);
return h265Frame;
}
while (ret >= 0) {
ret = avcodec_receive_packet(codecContext, &packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
// 处理接收编码数据失败的情况
av_packet_unref(&packet);
av_frame_free(&avFrame);
avcodec_free_context(&codecContext);
return h265Frame;
}
h265Frame = cv::Mat(packet.size, 1, CV_8UC1, packet.data);
av_packet_unref(&packet);
}
// 清理资源
av_frame_free(&avFrame);
avcodec_free_context(&codecContext);
return h265Frame;
}
```
你可以调用`cvMatToH265`函数,并将输入的cv::Mat作为参数传递给它,它会返回一个包含H265数据的cv::Mat。请注意,函数返回的cv::Mat仅包含编码后的H265数据,你需要根据需要将其解码和显示。
```cpp
cv::Mat inputFrame = cv::imread("input.jpg");
cv::Mat h265Data = cvMatToH265(inputFrame);
// 进行解码和显示
// ...
```
请确保你已正确设置了FFmpeg库以及相关头文件和库文件的路径。此外,注意在使用OpenCV之前,要确保正确包含相关的OpenCV头文件并连接正确的库文件。
c++ Mat 转 h264
要将 OpenCV 的 Mat 类型转换成 H.264 格式的视频,需要使用 FFmpeg 库。以下是一个简单的示例代码,可以将 Mat 类型的视频转换成 H.264 格式的视频:
```c++
#include <iostream>
#include <opencv2/opencv.hpp>
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
#include <libavutil/mathematics.h>
#include <libswscale/swscale.h>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
// OpenCV video capture
VideoCapture cap("video.mp4");
if (!cap.isOpened())
{
cerr << "Failed to open video file!" << endl;
return -1;
}
// FFmpeg encoder
avcodec_register_all();
AVCodec* codec = avcodec_find_encoder_by_name("libx264");
if (!codec)
{
cerr << "Codec not found!" << endl;
return -1;
}
AVCodecContext* codecCtx = avcodec_alloc_context3(codec);
if (!codecCtx)
{
cerr << "Failed to allocate codec context!" << endl;
return -1;
}
codecCtx->bit_rate = 400000;
codecCtx->width = cap.get(CAP_PROP_FRAME_WIDTH);
codecCtx->height = cap.get(CAP_PROP_FRAME_HEIGHT);
codecCtx->time_base = (AVRational){1, 25};
codecCtx->gop_size = 10;
codecCtx->max_b_frames = 1;
codecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
int ret = avcodec_open2(codecCtx, codec, NULL);
if (ret < 0)
{
cerr << "Failed to open codec: " << av_err2str(ret) << endl;
return -1;
}
// FFmpeg video output
AVFormatContext* fmtCtx = NULL;
ret = avformat_alloc_output_context2(&fmtCtx, NULL, NULL, "output.mp4");
if (ret < 0)
{
cerr << "Failed to allocate output context: " << av_err2str(ret) << endl;
return -1;
}
AVOutputFormat* fmt = fmtCtx->oformat;
if (fmt->video_codec == AV_CODEC_ID_NONE)
{
cerr << "No video codec found!" << endl;
return -1;
}
AVStream* stream = avformat_new_stream(fmtCtx, NULL);
if (!stream)
{
cerr << "Failed to allocate stream!" << endl;
return -1;
}
AVCodecContext* streamCtx = avcodec_alloc_context3(codec);
if (!streamCtx)
{
cerr << "Failed to allocate codec context!" << endl;
return -1;
}
ret = avcodec_parameters_from_context(stream->codecpar, streamCtx);
if (ret < 0)
{
cerr << "Failed to copy codec parameters: " << av_err2str(ret) << endl;
return -1;
}
stream->time_base = (AVRational){1, 25};
// Open output file
ret = avio_open(&fmtCtx->pb, "output.mp4", AVIO_FLAG_WRITE);
if (ret < 0)
{
cerr << "Failed to open output file: " << av_err2str(ret) << endl;
return -1;
}
// Write header
ret = avformat_write_header(fmtCtx, NULL);
if (ret < 0)
{
cerr << "Failed to write header: " << av_err2str(ret) << endl;
return -1;
}
SwsContext* swsCtx = sws_getContext(codecCtx->width, codecCtx->height, AV_PIX_FMT_BGR24,
codecCtx->width, codecCtx->height, codecCtx->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL);
AVFrame* frame = av_frame_alloc();
frame->format = codecCtx->pix_fmt;
frame->width = codecCtx->width;
frame->height = codecCtx->height;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0)
{
cerr << "Failed to allocate frame buffer: " << av_err2str(ret) << endl;
return -1;
}
AVPacket packet;
av_init_packet(&packet);
packet.data = NULL;
packet.size = 0;
while (true)
{
Mat frameMat;
cap >> frameMat;
if (frameMat.empty())
break;
// Convert OpenCV Mat to FFmpeg AVFrame
AVFrame* inputFrame = av_frame_alloc();
inputFrame->format = AV_PIX_FMT_BGR24;
inputFrame->width = frameMat.cols;
inputFrame->height = frameMat.rows;
ret = av_frame_get_buffer(inputFrame, 0);
if (ret < 0)
{
cerr << "Failed to allocate frame buffer: " << av_err2str(ret) << endl;
return -1;
}
uint8_t* inputData[AV_NUM_DATA_POINTERS] = {0};
inputData[0] = (uint8_t*)frameMat.data;
int inputLinesize[AV_NUM_DATA_POINTERS] = {0};
inputLinesize[0] = frameMat.step;
sws_scale(swsCtx, inputData, inputLinesize, 0, frameMat.rows, inputFrame->data, inputFrame->linesize);
// Encode frame
ret = avcodec_send_frame(codecCtx, inputFrame);
if (ret < 0)
{
cerr << "Failed to send frame: " << av_err2str(ret) << endl;
return -1;
}
while (ret >= 0)
{
ret = avcodec_receive_packet(codecCtx, &packet);
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
{
cerr << "Failed to receive packet: " << av_err2str(ret) << endl;
return -1;
}
if (ret >= 0)
{
av_packet_rescale_ts(&packet, codecCtx->time_base, stream->time_base);
packet.stream_index = stream->index;
ret = av_interleaved_write_frame(fmtCtx, &packet);
if (ret < 0)
{
cerr << "Failed to write packet: " << av_err2str(ret) << endl;
return -1;
}
av_packet_unref(&packet);
}
}
av_frame_unref(inputFrame);
}
// Flush encoder
ret = avcodec_send_frame(codecCtx, NULL);
if (ret < 0)
{
cerr << "Failed to send frame: " << av_err2str(ret) << endl;
return -1;
}
while (ret >= 0)
{
ret = avcodec_receive_packet(codecCtx, &packet);
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
{
cerr << "Failed to receive packet: " << av_err2str(ret) << endl;
return -1;
}
if (ret >= 0)
{
av_packet_rescale_ts(&packet, codecCtx->time_base, stream->time_base);
packet.stream_index = stream->index;
ret = av_interleaved_write_frame(fmtCtx, &packet);
if (ret < 0)
{
cerr << "Failed to write packet: " << av_err2str(ret) << endl;
return -1;
}
av_packet_unref(&packet);
}
}
// Write trailer
av_write_trailer(fmtCtx);
// Cleanup
avcodec_free_context(&codecCtx);
avcodec_free_context(&streamCtx);
av_frame_free(&frame);
avformat_free_context(fmtCtx);
return 0;
}
```
这段代码使用 OpenCV 从视频文件中读取每一帧图像,然后使用 FFmpeg 编码器将其转换成 H.264 格式,并写入输出文件。要使用此代码,需要先安装 FFmpeg 库并将其头文件和库文件路径添加到编译器的 include 和 lib 路径中。
阅读全文