欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

AVFrame和cv::Mat互转

程序员文章站 2022-07-01 23:30:28
...

音视频应用开发系列文章目录

ffmpeg视频解码后得到图像经常需要一些图像处理,opencv是图像处理的神器。所以就需要两者之间互相转化,ffmpeg解码后的数据类型是AVFrame,而opencv的图像数据结构是Mat,这就需要做个转化,本文实现了avframe->mat,mat->avframe。封装成函数

cv::Mat avframe_2_cvmat(AVFrame *avf, int w = 0, int h = 0);

AVFrame  *cvmat_2_avframe(cv::Mat);

avframe->mat

cv::Mat AvTools::avframe_2_cvmat(AVFrame *avf, int w, int h) {

	if (w <= 0) w = avf->width;
	if (h <= 0) h = avf->height;
	struct SwsContext *sws_ctx = NULL;
	sws_ctx = sws_getContext(avf->width, avf->height, (enum AVPixelFormat)avf->format,
		w, h, AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);

	cv::Mat mat;
	mat.create(cv::Size(w, h), CV_8UC3);
	AVFrame *bgr24frame = av_frame_alloc();
	bgr24frame->data[0] = (uint8_t *)mat.data;
	avpicture_fill((AVPicture *)bgr24frame, bgr24frame->data[0], AV_PIX_FMT_BGR24, w, h);

	sws_scale(sws_ctx,
		(const uint8_t* const*)avf->data, avf->linesize,
		0, avf->height, // from cols=0,all rows trans
		bgr24frame->data, bgr24frame->linesize);

	av_free(bgr24frame);
	sws_freeContext(sws_ctx);
	return mat;
}

w,h可以对输入图像进行resize,默认和原图大小一致,不resize。

mat->avframe

AVFrame *cvmat_2_avframe(cv::Mat mat, AVCodecContext *cdc_ctx) {

	cv::Mat yuv;
	// convert to yuv420p first
	cv::cvtColor(mat, yuv, cv::COLOR_BGR2YUV_I420);
	// calc frame size
	int frame_size = cdc_ctx->width * cdc_ctx->height;
	unsigned char *pdata = yuv.data;
	// fill yuv420
	// yyy yyy yyy yyy
	// uuu
	// vvv
	AVFrame *avf = av_frame_alloc();
	avf->data[0] = pdata; // fill y
	avf->data[1] = pdata + frame_size; // fill u
	avf->data[2] = pdata + frame_size * 5 / 4; // fill v
	avf->pts = pts_++; // seq
	// please call me LeiFeng
	return avf;
}

emmm···,注释的很清楚了!用完了别玩了释放AVFrame~~