记录AVFrame转化yuv,以及AVFrame2Mat

yuvToRgb(char * outSpace, int outWidth, int outHeight)
{
	mutex.lock();
	if (!iCtx || !yuv)
	{
		strcpy(errorbuf, "stream not open or yuv not decoded!");
		mutex.unlock();
		return false;
	}
	//设置转码器
	AVCodecContext * videoCtx = iCtx->streams[this->videoStream]->codec;
	vCtx = sws_getCachedContext(vCtx,
		videoCtx->width, videoCtx->height, videoCtx->pix_fmt,
		outWidth, outHeight, AV_PIX_FMT_BGRA,
		SWS_BICUBIC, NULL, NULL, NULL
	);
	if (!vCtx)
	{
		//失败
		strcpy(errorbuf, "sws getCachedContext failed!");
		mutex.unlock();
		return false;
	}
	//转码输出空间
	uint8_t *data[AV_NUM_DATA_POINTERS] = { 0 };
	data[0] = (uint8_t *)outSpace;
	//图像宽度
	int linesize[AV_NUM_DATA_POINTERS] = { 0 };
	linesize[0] = outWidth * 4;
	//转码,成功后返回转码图像的高
	int h = sws_scale(vCtx, yuv->data, yuv->linesize, 0, videoCtx->height,
		data, linesize);
	if (h <= 0)
	{
		//失败
		strcpy(errorbuf, "sws scale failed!");
		mutex.unlock();
		return false;
	}
	mutex.unlock();
	return true;
}
Mat avframe_to_cvmat(AVFrame *frame)
{
	AVFrame dst; 
	cv::Mat cvmat; 

	memset(&dst, 0, sizeof(dst)); 
	int w = frame->width, h = frame->height; 
	cvmat = cv::Mat(h, w, CV_8UC3); 
	dst.data[0] = (uint8_t *)cvmat.data; 
	avpicture_fill((AVPicture *)&dst, dst.data[0], AV_PIX_FMT_BGR24, w, h); 

	struct SwsContext *img_convert_ctx = NULL; 

	//enum PixelFormat src_pixfmt = (enum PixelFormat)frame->format; 
	AVPixelFormat src_pixfmt = (AVPixelFormat)frame->format; 
	//enum PixelFormat dst_pixfmt = AV_PIX_FMT_BGR24; 
	AVPixelFormat dst_pixfmt = AV_PIX_FMT_BGR24; 
	
	img_convert_ctx = sws_getContext(w, h, src_pixfmt, w, h, dst_pixfmt, SWS_FAST_BILINEAR, NULL, NULL, NULL); 
	sws_scale(img_convert_ctx, frame->data, frame->linesize, 0, h, dst.data, dst.linesize); 
	sws_freeContext(img_convert_ctx); 
	
	return cvmat;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用FFmpeg库将Mat YUV数据填充到AVFrame的示例代码: ```c++ #include <opencv2/opencv.hpp> #include <libavcodec/avcodec.h> int main(int argc, char* argv[]) { // 初始化FFmpegavcodec_register_all(); AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264); AVCodecContext* codec_ctx = avcodec_alloc_context3(codec); avcodec_open2(codec_ctx, codec, NULL); // 创建AVFrame对象 AVFrame* frame = av_frame_alloc(); frame->format = AV_PIX_FMT_YUV420P; frame->width = 1920; frame->height = 1080; av_frame_get_buffer(frame, 32); // 从Mat读取YUV数据 cv::Mat yuv_mat(1080 * 1.5, 1920, CV_8UC1); cv::Mat bgr_mat = cv::imread("test.jpg"); cv::cvtColor(bgr_mat, yuv_mat, cv::COLOR_BGR2YUV_I420); // 填充AVFrame memcpy(frame->data[0], yuv_mat.data, 1920 * 1080); memcpy(frame->data[1], yuv_mat.data + 1920 * 1080, 1920 * 540); memcpy(frame->data[2], yuv_mat.data + 1920 * 1080 + 1920 * 540, 1920 * 540); // 使用AVFrame进行解码等操作 // 释放资源 av_frame_free(&frame); avcodec_close(codec_ctx); avcodec_free_context(&codec_ctx); return 0; } ``` 在代码中,首先初始化了FFmpeg库并创建了AVCodecContext对象。然后创建AVFrame对象,并设置其格式、宽度和高度,并使用av_frame_get_buffer函数为其分配内存。 接着,从Mat对象中读取YUV数据,并使用memcpy函数将数据填充到AVFrame对象的data数组中。需要注意的是,YUV数据在data数组中的存储顺序为Y、U、V,而且U和V的宽度和高度都是原图的一半。 最后,使用AVFrame对象进行解码等操作,并在程序结束时释放资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值