2021-09-06

#pragma once

#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QGLShaderProgram>
#include <mutex>

class SDOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions, public IVideoView
{
	Q_OBJECT

public:
	explicit SDOpenGLWidget(QWidget *parent = nullptr);
	~SDOpenGLWidget();

	void InitView(int width, int height);

	void onUpdate(const uint8_t* source, int width, int height) override;

protected:
	void initializeGL() override;					//初始化GL
	void paintGL() override;						//刷新显示
	void resizeGL(int width, int height) override;	//窗口尺寸变化

private:
	void initDatas();
	void initTextures();

private:
	std::mutex			mMutex;

	QGLShaderProgram	mProgram;
	GLuint				mShaderPos[3]{ 0 };		//shader中的yuv变量地址
	GLuint				mTexPos[3]{ 0 };		//opengl的texture地址

	int					mWidth{ 640 };
	int					mHeight{ 480 };

	unsigned char*		mDatas{};				//材质的内存空间

	FILE*					mFile{};
};
#include <QDebug>
#include <QTimer>

#include "SDOpenGLWidget.h"


//自动加双引号
#define GET_STR(x) #x
#define A_VER 3
#define T_VER 4

//顶点shader
const char *vString = GET_STR(
	attribute vec4 vertexIn;
	attribute vec2 textureIn;
	varying vec2 textureOut;
	void main(void)
	{
		gl_Position = vertexIn;
		textureOut = textureIn;
	}
);
//片元shader
const char* tString = GET_STR(
	varying vec2 textureOut;
	uniform sampler2D tex_y;
	uniform sampler2D tex_u;
	uniform sampler2D tex_v;
	void main(void)
	{
		vec3 yuv;
		vec3 rgb;
		yuv.x = texture2D(tex_y, textureOut).r;
		yuv.y = texture2D(tex_u, textureOut).r - 0.5;
		yuv.z = texture2D(tex_v, textureOut).r - 0.5;
		rgb = mat3(1.0, 1.0, 1.0,
			0.0, -0.39465, 2.03211,
			1.13983, -0.58060, 0.0) * yuv;
		gl_FragColor = vec4(rgb, 1.0);
	}
);

SDOpenGLWidget::SDOpenGLWidget(QWidget *parent)
	: QOpenGLWidget(parent)
{
	//mFile = fopen("640x480.yuv","wb");
}

SDOpenGLWidget::~SDOpenGLWidget()
{
	if (mDatas)
	{
		mDatas = nullptr;
	}
	//清理材质空间
	if (mTexPos[0])
	{
		glDeleteTextures(3, mTexPos);
	}
}

void SDOpenGLWidget::InitView(int width, int height)
{
	mWidth = width;
	mHeight = height;
	initDatas();
	initTextures();
}

void SDOpenGLWidget::onUpdate(const uint8_t* source, int width, int height)
{
	mMutex.lock();
	memcpy(mDatas, source, mWidth*mHeight * 3 / 2);
	mMutex.unlock();
	update();
}

void SDOpenGLWidget::initializeGL()
{
	qCritical() << __FUNCTION__ << ":" << __LINE__;
	//初始化OpenGL(QOpenGLFunctions继承)函数
	initializeOpenGLFunctions();
	//program加载shader脚本(顶点和片元)脚本
	//片元(像素)
	qCritical() << __FUNCTION__ << ":" << __LINE__ << "loading gl_FragColor shader:" << mProgram.addShaderFromSourceCode(QGLShader::Fragment, tString);
	//顶点shader
	qCritical() << __FUNCTION__ << ":" << __LINE__ << "loading gl_Position shader:" << mProgram.addShaderFromSourceCode(QGLShader::Vertex, vString);
	//设置顶点坐标的变量
	mProgram.bindAttributeLocation("vertexIn", A_VER);
	//设置材质坐标
	mProgram.bindAttributeLocation("textureIn", T_VER);
	//编译shader
	qCritical() << __FUNCTION__ << ":" << __LINE__ << "link:" << mProgram.link();
	//绑定,将OpenGL与shader关联起来
	qCritical() << __FUNCTION__ << ":" << __LINE__ << "bind:" << mProgram.bind();

	//传递顶点和材质坐标
	//顶点
	static const GLfloat ver[] = {
		-1.0f, -1.0f,
		1.0f, -1.0f,
		-1.0f, 1.0f,
		1.0f, 1.0f
	};
	//材质
	static const GLfloat tex[] = {
		0.0f, 1.0f,
		1.0f, 1.0f,
		0.0f, 0.0f,
		1.0f, 0.0f
	};

	//顶点坐标初始化
	glVertexAttribPointer(A_VER, 2, GL_FLOAT, 0, 0, ver);
	glEnableVertexAttribArray(A_VER);
	//材质坐标初始化
	glVertexAttribPointer(T_VER, 2, GL_FLOAT, 0, 0, tex);
	glEnableVertexAttribArray(T_VER);

	//从shader获取材质
	mShaderPos[0] = mProgram.uniformLocation("tex_y");
	mShaderPos[1] = mProgram.uniformLocation("tex_u");
	mShaderPos[2] = mProgram.uniformLocation("tex_v");
}

void SDOpenGLWidget::paintGL()
{
	qCritical() << __FUNCTION__ << ":" << __LINE__;
	if (mDatas)
	{ 
		//fwrite(mDatas.get(), 1, mWidth*mHeight * 3 / 2, mFile);
		//fflush(mFile);
		mMutex.lock();

		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, mTexPos[0]);//0层绑定到Y材质
		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mWidth, mHeight, GL_RED, GL_UNSIGNED_BYTE, mDatas);//修改材质内容(复制内存中的内容)
		glUniform1i(mShaderPos[0], 0);//与shader中的yuv变量地址关联

		glActiveTexture(GL_TEXTURE0 + 1);
		glBindTexture(GL_TEXTURE_2D, mTexPos[1]);//1层绑定到U材质
		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mWidth / 2, mHeight / 2, GL_RED, GL_UNSIGNED_BYTE, mDatas + mWidth * mHeight);//修改材质内容(复制内存中的内容)
		glUniform1i(mShaderPos[1], 1);//与shader中的yuv变量地址关联

		glActiveTexture(GL_TEXTURE0 + 2);
		glBindTexture(GL_TEXTURE_2D, mTexPos[2]);//2层绑定到V材质
		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mWidth / 2, mHeight / 2, GL_RED, GL_UNSIGNED_BYTE, mDatas + mWidth * mHeight * 5 / 4);//修改材质内容(复制内存中的内容)
		glUniform1i(mShaderPos[2], 2);//与shader中的yuv变量地址关联

		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

		mMutex.unlock();

	}
}

void SDOpenGLWidget::resizeGL(int width, int height)
{
	qCritical() << __FUNCTION__ << ":" << __LINE__ << width << ":" << height;
}

void SDOpenGLWidget::initDatas()
{
	mMutex.lock();

	if (mDatas)
	{
		delete mDatas;
		mDatas = nullptr;
	}
	mDatas = new unsigned char[mWidth*mHeight * 3 / 2];

	mMutex.unlock();
}

void SDOpenGLWidget::initTextures()
{
	mMutex.lock();

	//清理材质空间
	if (mTexPos[0])
	{
		glDeleteTextures(3, mTexPos);
	}
	//创建材质
	glGenTextures(3, mTexPos);

	//Y
	glBindTexture(GL_TEXTURE_2D, mTexPos[0]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//放大过滤,(GL_LINEAR,线性差值; GL_NEAREST,临近差值,效率高单马赛克严重)
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//缩小过滤,线性差值
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, mWidth, mHeight, 0, GL_RED, GL_UNSIGNED_BYTE, 0);//创建材质显卡空间
	//U
	glBindTexture(GL_TEXTURE_2D, mTexPos[1]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//放大过滤,线性差值
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//缩小过滤,线性差值
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, mWidth / 2, mHeight / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);//创建材质显卡空间
	//V
	glBindTexture(GL_TEXTURE_2D, mTexPos[2]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//放大过滤,线性差值
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//缩小过滤,线性差值
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, mWidth / 2, mHeight / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);//创建材质显卡空间

	mMutex.unlock();
}

WebRtc实时拉流数据:

void SDVideoRenderer::OnFrame(const webrtc::VideoFrame& frame)
{
	mMutex.lock();

	rtc::scoped_refptr<webrtc::I420BufferInterface> buffer(frame.video_frame_buffer()->ToI420());
	if (buffer == nullptr)
	{
		return;
	}
	if (frame.rotation() != webrtc::kVideoRotation_0)
	{
		buffer = webrtc::I420Buffer::Rotate(*buffer, frame.rotation());
	}
	int nwidth = buffer->width();
	int nheight = buffer->height();


	if (mVideoView)
	{
		mVideoView->onUpdate(buffer->DataY(), nwidth, nheight);
	}

	mMutex.unlock();
}

使用python中的pymsql完成如下:表结构与数据创建 1. 建立 `users` 表和 `orders` 表。 `users` 表有用户ID、用户名、年龄字段,(id,name,age) `orders` 表有订单ID、订单日期、订单金额,用户id字段。(id,order_date,amount,user_id) 2 两表的id作为主键,`orders` 表用户id为users的外键 3 插入数据 `users` (1, '张三', 18), (2, '李四', 20), (3, '王五', 22), (4, '赵六', 25), (5, '钱七', 28); `orders` (1, '2021-09-01', 500, 1), (2, '2021-09-02', 1000, 2), (3, '2021-09-03', 600, 3), (4, '2021-09-04', 800, 4), (5, '2021-09-05', 1500, 5), (6, '2021-09-06', 1200, 3), (7, '2021-09-07', 2000, 1), (8, '2021-09-08', 300, 2), (9, '2021-09-09', 700, 5), (10, '2021-09-10', 900, 4); 查询语句 1. 查询订单总金额 2. 查询所有用户的平均年龄,并将结果四舍五入保留两位小数。 3. 查询订单总数最多的用户的姓名和订单总数。 4. 查询所有不重复的年龄。 5. 查询订单日期在2021年9月1日至9月4日之间的订单总金额。 6. 查询年龄不大于25岁的用户的订单数量,并按照降序排序。 7. 查询订单总金额排名前3的用户的姓名和订单总金额。 8. 查询订单总金额最大的用户的姓名和订单总金额。 9. 查询订单总金额最小的用户的姓名和订单总金额。 10. 查询所有名字中含有“李”的用户,按照名字升序排序。 11. 查询所有年龄大于20岁的用户,按照年龄降序排序,并只显示前5条记录。 12. 查询每个用户的订单数量和订单总金额,并按照总金额降序排序。
最新发布
06-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值