mirror of
https://github.com/barry-ran/QtScrcpy.git
synced 2025-08-04 14:48:37 +00:00
opengl渲染yuv成功
This commit is contained in:
parent
e699468595
commit
131ade1736
4 changed files with 35 additions and 67 deletions
|
@ -80,31 +80,6 @@ void Decoder::stopDecode()
|
||||||
wait();
|
wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveAVFrame_YUV_ToTempFile(AVFrame *pFrame, QByteArray& buffer)
|
|
||||||
{
|
|
||||||
int t_frameWidth = pFrame->width;
|
|
||||||
int t_frameHeight = pFrame->height;
|
|
||||||
int t_yPerRowBytes = pFrame->linesize[0];
|
|
||||||
int t_uPerRowBytes = pFrame->linesize[1];
|
|
||||||
int t_vPerRowBytes = pFrame->linesize[2];
|
|
||||||
|
|
||||||
for(int i = 0;i< t_frameHeight ;i++)
|
|
||||||
{
|
|
||||||
buffer.append((char*)(pFrame->data[0]+i*t_yPerRowBytes), t_frameWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0;i< t_frameHeight/2 ;i++)
|
|
||||||
{
|
|
||||||
buffer.append((char*)(pFrame->data[1]+i*t_uPerRowBytes), t_frameWidth/2);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0;i< t_frameHeight/2 ;i++)
|
|
||||||
{
|
|
||||||
buffer.append((char*)(pFrame->data[2]+i*t_vPerRowBytes), t_frameWidth/2);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Decoder::run()
|
void Decoder::run()
|
||||||
{
|
{
|
||||||
unsigned char *decoderBuffer = Q_NULLPTR;
|
unsigned char *decoderBuffer = Q_NULLPTR;
|
||||||
|
@ -118,7 +93,6 @@ void Decoder::run()
|
||||||
AVFrame* rgbDecoderFrame = Q_NULLPTR;
|
AVFrame* rgbDecoderFrame = Q_NULLPTR;
|
||||||
yuvDecoderFrame = av_frame_alloc();
|
yuvDecoderFrame = av_frame_alloc();
|
||||||
rgbDecoderFrame = av_frame_alloc();
|
rgbDecoderFrame = av_frame_alloc();
|
||||||
quint8 *outBuffer = Q_NULLPTR;
|
|
||||||
|
|
||||||
bool isFormatCtxOpen = false;
|
bool isFormatCtxOpen = false;
|
||||||
bool isCodecCtxOpen = false;
|
bool isCodecCtxOpen = false;
|
||||||
|
@ -189,10 +163,13 @@ void Decoder::run()
|
||||||
ret = avcodec_receive_frame(codecCtx, yuvDecoderFrame);
|
ret = avcodec_receive_frame(codecCtx, yuvDecoderFrame);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
// a frame was received
|
// a frame was received
|
||||||
QByteArray buffer;
|
emit getOneFrame(yuvDecoderFrame->data[0], yuvDecoderFrame->data[1], yuvDecoderFrame->data[2],
|
||||||
saveAVFrame_YUV_ToTempFile(yuvDecoderFrame, buffer);
|
yuvDecoderFrame->linesize[0], yuvDecoderFrame->linesize[1], yuvDecoderFrame->linesize[2]);
|
||||||
emit getOneFrame(buffer, codecCtx->width, codecCtx->height);
|
qDebug() << "emit getOneFrame";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
// m_conver转换yuv为rgb是使用cpu转的,占用cpu太高,改用opengl渲染yuv
|
||||||
|
// QImage的copy也非常占用内存,此方案不考虑
|
||||||
if (!m_conver.isInit()) {
|
if (!m_conver.isInit()) {
|
||||||
qDebug() << "decoder frame format" << yuvDecoderFrame->format;
|
qDebug() << "decoder frame format" << yuvDecoderFrame->format;
|
||||||
m_conver.setSrcFrameInfo(codecCtx->width, codecCtx->height, AV_PIX_FMT_YUV420P);
|
m_conver.setSrcFrameInfo(codecCtx->width, codecCtx->height, AV_PIX_FMT_YUV420P);
|
||||||
|
@ -203,14 +180,9 @@ void Decoder::run()
|
||||||
outBuffer=new quint8[avpicture_get_size(AV_PIX_FMT_RGB32, codecCtx->width, codecCtx->height)];
|
outBuffer=new quint8[avpicture_get_size(AV_PIX_FMT_RGB32, codecCtx->width, codecCtx->height)];
|
||||||
avpicture_fill((AVPicture *)rgbDecoderFrame, outBuffer, AV_PIX_FMT_RGB32, codecCtx->width, codecCtx->height);
|
avpicture_fill((AVPicture *)rgbDecoderFrame, outBuffer, AV_PIX_FMT_RGB32, codecCtx->width, codecCtx->height);
|
||||||
}
|
}
|
||||||
// tc games 3% ???
|
m_conver.convert(yuvDecoderFrame, rgbDecoderFrame);
|
||||||
// scrcpy 7% cpu
|
|
||||||
// 5% cpu
|
|
||||||
//m_conver.convert(yuvDecoderFrame, rgbDecoderFrame);
|
|
||||||
// 8% cpu
|
|
||||||
//QImage tmpImg((uchar *)outBuffer, codecCtx->width, codecCtx->height, QImage::Format_RGB32);
|
//QImage tmpImg((uchar *)outBuffer, codecCtx->width, codecCtx->height, QImage::Format_RGB32);
|
||||||
//QImage image = tmpImg.copy(); //把图像复制一份 传递给界面显示
|
//QImage image = tmpImg.copy();
|
||||||
// 16% cpu
|
|
||||||
//emit getOneImage(image);
|
//emit getOneImage(image);
|
||||||
*/
|
*/
|
||||||
} else if (ret != AVERROR(EAGAIN)) {
|
} else if (ret != AVERROR(EAGAIN)) {
|
||||||
|
@ -258,9 +230,6 @@ runQuit:
|
||||||
avcodec_free_context(&codecCtx);
|
avcodec_free_context(&codecCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outBuffer) {
|
|
||||||
delete[] outBuffer;
|
|
||||||
}
|
|
||||||
if (yuvDecoderFrame) {
|
if (yuvDecoderFrame) {
|
||||||
av_free(yuvDecoderFrame);
|
av_free(yuvDecoderFrame);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@ public:
|
||||||
void stopDecode();
|
void stopDecode();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void getOneFrame(QByteArray buffer, quint32 width, quint32 height);
|
void getOneFrame(quint8* bufferY, quint8* bufferU, quint8* bufferV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
|
|
|
@ -21,25 +21,15 @@ GLYuvWidget::~GLYuvWidget()
|
||||||
doneCurrent();
|
doneCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLYuvWidget::slotShowYuv(QByteArray buffer, uint width, uint height)
|
void GLYuvWidget::slotShowYuv(quint8* bufferY, quint8* bufferU, quint8* bufferV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV)
|
||||||
{
|
{
|
||||||
m_videoWidth = width;
|
qDebug() << "slotShowYuv";
|
||||||
m_videoHeight = height;
|
m_bufferY = bufferY;
|
||||||
|
m_bufferU = bufferU;
|
||||||
QFile *file = new QFile;
|
m_bufferV = bufferV;
|
||||||
file->setFileName("android.yuv");
|
m_linesizeY = linesizeY;
|
||||||
bool ok = file->open(QIODevice::WriteOnly | QIODevice::Append);
|
m_linesizeU = linesizeU;
|
||||||
if(ok) {
|
m_linesizeV = linesizeV;
|
||||||
QDataStream out(file);
|
|
||||||
//out.setVersion(QDataStream::Qt_5_7);
|
|
||||||
out << buffer;
|
|
||||||
file->close();
|
|
||||||
delete(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_buffer.setRawData(buffer, buffer.size());
|
|
||||||
m_yuvPtr = m_buffer.data();
|
|
||||||
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,8 +136,9 @@ void GLYuvWidget::inittexture()
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0); //激活纹理单元GL_TEXTURE0,系统里面的
|
glActiveTexture(GL_TEXTURE0); //激活纹理单元GL_TEXTURE0,系统里面的
|
||||||
glBindTexture(GL_TEXTURE_2D, m_idY); //绑定y分量纹理对象id到激活的纹理单元
|
glBindTexture(GL_TEXTURE_2D, m_idY); //绑定y分量纹理对象id到激活的纹理单元
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, m_linesizeY);
|
||||||
//使用内存中的数据创建真正的y分量纹理数据
|
//使用内存中的数据创建真正的y分量纹理数据
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_videoWidth, m_videoHeight, 0, GL_RED, GL_UNSIGNED_BYTE, m_yuvPtr);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_videoWidth, m_videoHeight, 0, GL_RED, GL_UNSIGNED_BYTE, m_bufferY);
|
||||||
//https://blog.csdn.net/xipiaoyouzi/article/details/53584798 纹理参数解析
|
//https://blog.csdn.net/xipiaoyouzi/article/details/53584798 纹理参数解析
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
@ -156,8 +147,9 @@ void GLYuvWidget::inittexture()
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE1); //激活纹理单元GL_TEXTURE1
|
glActiveTexture(GL_TEXTURE1); //激活纹理单元GL_TEXTURE1
|
||||||
glBindTexture(GL_TEXTURE1, m_idU);
|
glBindTexture(GL_TEXTURE1, m_idU);
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, m_linesizeU);
|
||||||
//使用内存中的数据创建真正的u分量纹理数据
|
//使用内存中的数据创建真正的u分量纹理数据
|
||||||
glTexImage2D(GL_TEXTURE_2D,0,GL_RED, m_videoWidth >> 1, m_videoHeight >> 1, 0, GL_RED, GL_UNSIGNED_BYTE, m_yuvPtr + m_videoWidth * m_videoHeight);
|
glTexImage2D(GL_TEXTURE_2D,0,GL_RED, m_videoWidth >> 1, m_videoHeight >> 1, 0, GL_RED, GL_UNSIGNED_BYTE, m_bufferU);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
@ -165,8 +157,9 @@ void GLYuvWidget::inittexture()
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE2); //激活纹理单元GL_TEXTURE2
|
glActiveTexture(GL_TEXTURE2); //激活纹理单元GL_TEXTURE2
|
||||||
glBindTexture(GL_TEXTURE_2D, m_idV);
|
glBindTexture(GL_TEXTURE_2D, m_idV);
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, m_linesizeV);
|
||||||
//使用内存中的数据创建真正的v分量纹理数据
|
//使用内存中的数据创建真正的v分量纹理数据
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_videoWidth >> 1, m_videoHeight >> 1, 0, GL_RED, GL_UNSIGNED_BYTE, m_yuvPtr + m_videoWidth * m_videoHeight * 5 / 4);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_videoWidth >> 1, m_videoHeight >> 1, 0, GL_RED, GL_UNSIGNED_BYTE, m_bufferV);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
@ -175,6 +168,7 @@ void GLYuvWidget::inittexture()
|
||||||
|
|
||||||
void GLYuvWidget::paintGL()
|
void GLYuvWidget::paintGL()
|
||||||
{
|
{
|
||||||
|
qDebug() << "paintGL()";
|
||||||
inittexture();
|
inittexture();
|
||||||
//指定y纹理要使用新值
|
//指定y纹理要使用新值
|
||||||
glUniform1i(m_textureUniformY, 0);
|
glUniform1i(m_textureUniformY, 0);
|
||||||
|
|
|
@ -18,7 +18,7 @@ public:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
//显示一帧Yuv图像
|
//显示一帧Yuv图像
|
||||||
void slotShowYuv(QByteArray buffer, uint width, uint height);
|
void slotShowYuv(quint8* bufferY, quint8* bufferU, quint8* bufferV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void initializeGL() Q_DECL_OVERRIDE;
|
void initializeGL() Q_DECL_OVERRIDE;
|
||||||
|
@ -45,11 +45,15 @@ private:
|
||||||
GLuint m_idV = 0;
|
GLuint m_idV = 0;
|
||||||
|
|
||||||
// 视频宽高
|
// 视频宽高
|
||||||
quint32 m_videoWidth;
|
quint32 m_videoWidth = 1080;
|
||||||
quint32 m_videoHeight;
|
quint32 m_videoHeight = 2160;
|
||||||
|
|
||||||
char *m_yuvPtr = Q_NULLPTR;
|
quint8* m_bufferY = Q_NULLPTR;
|
||||||
QByteArray m_buffer;
|
quint8* m_bufferU = Q_NULLPTR;
|
||||||
|
quint8* m_bufferV = Q_NULLPTR;
|
||||||
|
quint32 m_linesizeY = 0;
|
||||||
|
quint32 m_linesizeU = 0;
|
||||||
|
quint32 m_linesizeV = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GLYUVWIDGET_H
|
#endif // GLYUVWIDGET_H
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue