音视频开发系列(6):opencv打开摄像头进行播放,并且进行像素格式转换

好久没更新博客了,最近在交毕设的材料耽搁了学习的时间,今天继续开始进行音视频学习的记录,上次利用rtmp进行推流完成了一个基本的流媒体直播,这次要利用本地的摄像头采集视频帧然后利用rtmp将采集到的视频上传到服务器进行直播,这次需要利用opencv和ffmpeg的库进行,所以在编写代码之前需要对项目进行配置。

音视频开发系列(6):opencv打开摄像头进行播放,并且进行像素格式转换_第1张图片

文件夹的目录还是与之前的一致,bin文件夹存放生成的文件,include文件夹存放头文件,lib文件夹存放库文件,src文件夹存放源代码。

配置的方法还是和之前的一致,在属性中的常规将生成的路径修改成bin文件夹。

音视频开发系列(6):opencv打开摄像头进行播放,并且进行像素格式转换_第2张图片

头文件目录

音视频开发系列(6):opencv打开摄像头进行播放,并且进行像素格式转换_第3张图片 

库文件目录

音视频开发系列(6):opencv打开摄像头进行播放,并且进行像素格式转换_第4张图片 

配置好以后就可以进行编写代码了。

利用opencv的VideoCapture类中的open函数打开摄像头,我这边由于打开的是电脑的摄像头,所以直接使用下标0。

然后这边使用c++的异常机制,try-catch函数,当出现打开摄像头异常的时候,直接抛出错误,如果没有这么处理的话,打开摄像头失败还进行读帧的话程序会卡掉。

然后利用opencv中的grab函数读取视频帧并进行解码,再利用retrieve函数将读取到yuv格式转化rgb格式。

然后就可以利用opencv的nameWindow创建一个窗口,然后利用imshow将读取的视频帧显示出来。

由于将视频帧推流到服务器上需要.h264的视频,所以需要将rgb格式的图片转化成yuv格式的才可以进行编码,这时候就需要用到ffmpeg的sws_getCachedContext()函数进行转化,该函数的参数如下所示。

struct SwsContext *context,
int srcW, int srcH, 原宽高
enum AVPixelFormat srcFormat,原像素格式
int dstW, int dstH, 目标宽高
enum AVPixelFormat dstFormat,目标格式
int flags, 算法标签(性能差异 效果差异 针对尺寸变化)
SwsFilter *srcFilter,过滤器
SwsFilter *dstFilter,过滤器
const double *param 算法中默认值的设定 可以默认);
两个函数的差别是第一个参数:SwsContext
sws_getContext 会创建一个上下文空间,sws_getCachedContext会去缓冲中找,前后两次参数没变时返回同一个。

这次只是分享如何初始化像素格式上下文,下面是具体代码的分享。

#include 
#include 
extern "C"
{
#include 
}
using namespace std;
using namespace cv;
#pragma comment(lib,"opencv_world320.lib")
#pragma comment(lib,"swscale.lib")
int main(int argc,char *argv[])
{
	//nginx-rtmp 直播服务器rtmp推流URL
	char *outUrl = "rtmp://192.168.198.128/live";
	VideoCapture cam;
	Mat frame;
	namedWindow("video");
	//像素格式转换上下文
	SwsContext *vsc = NULL;
	try 
	{
		//使用opencv打开本地相机
		cam.open(0);
		///1.打开摄像头
		if (!cam.isOpened())
		{
			throw exception("cam open failed!");
		}
		cout << "cam open success" << endl;
		int inWidth = cam.get(CAP_PROP_FRAME_WIDTH);
		int inHeight = cam.get(CAP_PROP_FRAME_HEIGHT);
		///2 初始化格式转换上下文
		vsc = sws_getCachedContext(vsc,
			//源宽、高、像素格式
			inWidth,inHeight, AV_PIX_FMT_BGR24,
			//目标宽、高、像素格式
			inWidth, inHeight,AV_PIX_FMT_YUV420P,
			SWS_BICUBIC,  //尺寸变化使用的算法
			0,0,0
			);
		if (!vsc)
		{
			throw exception("sws_getCachedContext failed!");
		}
		//读取帧
		for (;;)
		{
			//只做解码,读取视频帧,解码视频帧
			if (!cam.grab())
			{
				continue;
			}
			//yuv转化为rgb
			if (!cam.retrieve(frame))
			{
				continue;
			}
			imshow("video", frame);
			waitKey(1);
			//rgb to yuv
			//h264编码
			//推流
		}
	}
	catch (exception &ex)
	{
		if (cam.isOpened())
			cam.release();
		if (vsc)
		{
			sws_freeContext(vsc);
			vsc = NULL;
		}
		cerr << ex.what() << endl;
	}
	getchar();
	return 0;
}

你可能感兴趣的:(音视频开发,c++,音视频,opencv)