当前位置:网站首页>Player practice 17 xvideowidget
Player practice 17 xvideowidget
2022-06-12 14:09:00 【Sister Suo】
int main(int argc, char *argv[])
{
testtread tt;
tt.init();
QApplication a(argc, argv);
Xplay2 w;
w.show();
w.ui.openGLWidget->Init(tt.demux.width, tt.demux.height);
tt.video = w.ui.openGLWidget;
tt.start();
return a.exec();
}
In actual combat 14 in , It is read directly yuv One fan divided into one request OpenGL Drawing :
fp = fopen(“out240x128.yuv”, “rb”);
Here we get it by decoding frame To draw
open .ui file , add to OpenGL Control :
Promote to class xvideowidget:
stay ui_Xplay2 You can see the following code in the file :
class Ui_Xplay2Class
{
public:
xvideowidget *openGLWidget;
void setupUi(QWidget *Xplay2Class)
{
if (Xplay2Class->objectName().isEmpty())
Xplay2Class->setObjectName(QString::fromUtf8("Xplay2Class"));
Xplay2Class->resize(1072, 790);
openGLWidget = new xvideowidget(Xplay2Class);
openGLWidget->setObjectName(QString::fromUtf8("openGLWidget"));
openGLWidget->setGeometry(QRect(149, 129, 800, 600));
retranslateUi(Xplay2Class);
QMetaObject::connectSlotsByName(Xplay2Class);
} // setupUi
void retranslateUi(QWidget *Xplay2Class)
{
Xplay2Class->setWindowTitle(QCoreApplication::translate("Xplay2Class", "Xplay2", nullptr));
} // retranslateUi
};
You can see xvideowidget *openGLWidget; Put a point in the big class of this interface xvideowidget The pointer to OpenGLwidget, And call with this pointer resize Other methods
Add... To the code xvideowidget.h:
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QGLShaderProgram>
#include <mutex>
struct AVFrame;
class xvideowidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
void Init(int width, int height);
// Whether successful or not, release frame Space
virtual void Repaint(AVFrame* frame);
xvideowidget(QWidget* parent);
~xvideowidget();
protected:
// Refresh the display
void paintGL();
// initialization gl
void initializeGL();
// Window size change
void resizeGL(int width, int height);
private:
std::mutex mux;
//shader Program
QGLShaderProgram program;
//shader in yuv Variable address
GLuint unis[3] = {
0 };
//openg Of texture Address
GLuint texs[3] = {
0 };
// Material memory space
unsigned char* datas[3] = {
0 };
int width = 0;
int height = 0;
};
xvideowidget.cpp And actual combat 14 The difference is the actual combat 14 The width and height of the lieutenant general are determined in advance , Here, the width and height are set according to the transmitted data , And provides a new interface , The purpose is to set the width and height , Allocate material memory space , Set the zoom in / out method :
void xvideowidget::Init(int width, int height)
{
mux.lock();
this->width = width;
this->height = height;
delete datas[0];
delete datas[1];
delete datas[2];
/// Allocate material memory space
datas[0] = new unsigned char[width * height]; //Y
datas[1] = new unsigned char[width * height / 4]; //U
datas[2] = new unsigned char[width * height / 4]; //V
if (texs[0])
{
glDeleteTextures(3, texs);
}
// Create materials
glGenTextures(3, texs);
//Y
glBindTexture(GL_TEXTURE_2D, texs[0]);
// Zoom in and filter , linear interpolation GL_NEAREST( Efficient , But mosaic is serious )
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Create material graphics card space
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
//U
glBindTexture(GL_TEXTURE_2D, texs[1]);
// Zoom in and filter , linear interpolation
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Create material graphics card space
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
//V
glBindTexture(GL_TEXTURE_2D, texs[2]);
// Zoom in and filter , linear interpolation
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Create material graphics card space
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
mux.unlock();
}
Because creating materials also uses height and width , So put it into this interface
Creating material graphics card space requires tex, Deleting will also delete tex, In order to prevent half of the application from being deleted, resulting in program downtime , Put a lock on it , Used by other functions data And tex And lock the , about repaint() This kind of frequent , Pay attention to the amount of code locked , Will affect performance , about init It doesn't matter if it only happens once
Reading and drawing will block , Therefore use QThread:
class testtread :public QThread
{
public:
void init()
{
const char* path = "E:\\ffmpeg\\test.mp4";
const char* url = "rtsp://27.22.78.122:8554/1";
cout << "demux.Open = " << demux.Open(path) << endl;
cout << "vdecode.open()" << vdecode.open(demux.CopyVPara()) << endl;
cout << "adecode.open()" << adecode.open(demux.CopyAPara()) << endl;
}
void run()
{
for (;;)
{
AVPacket* pkt = demux.readfz();
if (demux.isvideo(pkt) == true)
{
vdecode.send(pkt);
AVFrame* frame = vdecode.receive();
//cout << " Video decoding " <<frame<< endl;
video->Repaint(frame);
Sleep(40);
}
else
{
//adecode.send(pkt);
//AVFrame* frame = adecode.receive();
//cout << " Audio decoding " <<frame<< endl;
}
if (!pkt)break;
}
}
xdemux demux;
xvideowidget* video;
protected:
xdecode vdecode;
xdecode adecode;
};
Because after the main thread exits video Have been deleted , However, the thread is still , So there will be some small problems , We'll deal with it later
main function :
int main(int argc, char *argv[])
{
testtread tt;
tt.init();
QApplication a(argc, argv);
Xplay2 w;
w.show();
w.ui.openGLWidget->Init(tt.demux.width, tt.demux.height);
tt.video = w.ui.openGLWidget;
tt.start();
return a.exec();
}
1. Instantiate a thread ,
Instantiating a thread also instantiates demux,vdecode,adecode,xvideowidget*, And transmit the unpacked video information to vdecode, Audio information is transmitted to adecode
2. Open one QT The window of
3. Transmit the width and height information obtained by unpacking to ui The initialization function of the control added in the window , Give Way QT A video window with the same width and height as our media file can be displayed on the window , It just can't display the picture
tt Of demux And video,w Of ui Are all out of class accesses , So let's open these members to public
4. Let the point in the thread xvideowidget The pointer to the control we added , call start That is, the of the calling thread run, stay run Will be decoded in packet issue openg Draw and display on the control
void xvideowidget::Repaint(AVFrame* frame)
{
if (!frame)
{
qDebug() << "show failed1" ;
return;
}
mux.lock();
// Fault tolerance , Make sure the dimensions are correct
if (!datas[0] || width * height == 0 || frame->width != this->width || frame->height != this->height)
{
av_frame_free(&frame);
mux.unlock();
qDebug() << "show failed2";
return;
}
memcpy(datas[0], frame->data[0], width * height);
memcpy(datas[1], frame->data[1], width * height / 4);
memcpy(datas[2], frame->data[2], width * height / 4);
// Row alignment problem
mux.unlock();
// Refresh the display
update();
qDebug()<< "repaint" ;
}
The operation is as follows :
边栏推荐
- Is Shell Scripting really a big technology?
- 【mysql进阶】查询优化原理与方案(六)
- Running phase of SystemC
- Redis core configuration and advanced data types
- Programmer interview golden classic good question / interview question 01.05 Edit once
- Dismantle and modify the advertising machine - Amateur decompression
- 程序分析与优化 - 6 循环优化
- 280 weeks /2171 Take out the least number of magic beans
- Socket model of punctual atom stm32f429 core board
- Acwing: topology sequence
猜你喜欢
拆改广告机---业余解压
[wustctf2020] selfie score query -1
Summary of virtual box usage problems
Create a small root heap and judge the node relationship (also.C\u str() substr(),atoi(),string. Use of find())
Design of PLC intelligent slave station based on PROFIBUS DP protocol
TestEngine with ID ‘junit-vintage‘ failed to discover tests
CSDN blog points rule
Implementation of Ackermann function with simulated recursion
[video lesson] a full set of tutorials on the design and production of Android studio Internet of things app -- all mastered during the National Day
如何使用android studio制作一个阿里云物联网APP
随机推荐
高考回忆录
Implementation of Ackermann function with simulated recursion
If you want to build brand awareness, what bidding strategy can you choose?
浅谈中国程序员为什么要跳槽?
Axi4 increase burst / wrap burst/ fix burst and narrow transfer
After reading the question, you will point to offer 16 Integer power of numeric value
Lua common built-in functions
如何使用android studio制作一个阿里云物联网APP
Xcode debugging OpenGLES
肝了一个月的原创小袁个人博客项目开源啦(博客基本功能都有,还包含后台管理)
Dynamic search advertising intelligent search for matching keywords
A method of quickly creating test window
Is MySQL query limit 1000,10 as fast as limit 10? How to crack deep paging
什么是自动出价?它的优势是什么?
Remote code injection
Dismantle and modify the advertising machine - Amateur decompression
Player screen orientation scheme
Relevant knowledge points of cocoapods
969. pancake sorting
十四周作业