diff --git a/src/decoder.cpp b/src/decoder.cpp index 09f8566..2169b88 100644 --- a/src/decoder.cpp +++ b/src/decoder.cpp @@ -80,31 +80,6 @@ void Decoder::stopDecode() 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() { unsigned char *decoderBuffer = Q_NULLPTR; @@ -118,7 +93,6 @@ void Decoder::run() AVFrame* rgbDecoderFrame = Q_NULLPTR; yuvDecoderFrame = av_frame_alloc(); rgbDecoderFrame = av_frame_alloc(); - quint8 *outBuffer = Q_NULLPTR; bool isFormatCtxOpen = false; bool isCodecCtxOpen = false; @@ -189,10 +163,13 @@ void Decoder::run() ret = avcodec_receive_frame(codecCtx, yuvDecoderFrame); if (!ret) { // a frame was received - QByteArray buffer; - saveAVFrame_YUV_ToTempFile(yuvDecoderFrame, buffer); - emit getOneFrame(buffer, codecCtx->width, codecCtx->height); + emit getOneFrame(yuvDecoderFrame->data[0], yuvDecoderFrame->data[1], yuvDecoderFrame->data[2], + yuvDecoderFrame->linesize[0], yuvDecoderFrame->linesize[1], yuvDecoderFrame->linesize[2]); + qDebug() << "emit getOneFrame"; + /* + // m_conver转换yuv为rgb是使用cpu转的,占用cpu太高,改用opengl渲染yuv + // QImage的copy也非常占用内存,此方案不考虑 if (!m_conver.isInit()) { qDebug() << "decoder frame format" << yuvDecoderFrame->format; m_conver.setSrcFrameInfo(codecCtx->width, codecCtx->height, AV_PIX_FMT_YUV420P); @@ -202,15 +179,10 @@ void Decoder::run() if (!outBuffer) { 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); - } - // tc games 3% ??? - // scrcpy 7% cpu - // 5% cpu - //m_conver.convert(yuvDecoderFrame, rgbDecoderFrame); - // 8% cpu + } + m_conver.convert(yuvDecoderFrame, rgbDecoderFrame); //QImage tmpImg((uchar *)outBuffer, codecCtx->width, codecCtx->height, QImage::Format_RGB32); - //QImage image = tmpImg.copy(); //把图像复制一份 传递给界面显示 - // 16% cpu + //QImage image = tmpImg.copy(); //emit getOneImage(image); */ } else if (ret != AVERROR(EAGAIN)) { @@ -258,9 +230,6 @@ runQuit: avcodec_free_context(&codecCtx); } - if (outBuffer) { - delete[] outBuffer; - } if (yuvDecoderFrame) { av_free(yuvDecoderFrame); } diff --git a/src/decoder.h b/src/decoder.h index aa98336..ddce443 100644 --- a/src/decoder.h +++ b/src/decoder.h @@ -30,7 +30,8 @@ public: void stopDecode(); signals: - void getOneFrame(QByteArray buffer, quint32 width, quint32 height); + void getOneFrame(quint8* bufferY, quint8* bufferU, quint8* bufferV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV); + protected: void run(); diff --git a/src/glyuvwidget.cpp b/src/glyuvwidget.cpp index ef23a5c..4dfb823 100644 --- a/src/glyuvwidget.cpp +++ b/src/glyuvwidget.cpp @@ -21,25 +21,15 @@ GLYuvWidget::~GLYuvWidget() 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; - m_videoHeight = height; - - QFile *file = new QFile; - file->setFileName("android.yuv"); - bool ok = file->open(QIODevice::WriteOnly | QIODevice::Append); - if(ok) { - 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(); - + qDebug() << "slotShowYuv"; + m_bufferY = bufferY; + m_bufferU = bufferU; + m_bufferV = bufferV; + m_linesizeY = linesizeY; + m_linesizeU = linesizeU; + m_linesizeV = linesizeV; update(); } @@ -146,8 +136,9 @@ void GLYuvWidget::inittexture() glActiveTexture(GL_TEXTURE0); //激活纹理单元GL_TEXTURE0,系统里面的 glBindTexture(GL_TEXTURE_2D, m_idY); //绑定y分量纹理对象id到激活的纹理单元 + glPixelStorei(GL_UNPACK_ROW_LENGTH, m_linesizeY); //使用内存中的数据创建真正的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 纹理参数解析 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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 glBindTexture(GL_TEXTURE1, m_idU); + glPixelStorei(GL_UNPACK_ROW_LENGTH, m_linesizeU); //使用内存中的数据创建真正的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_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -165,8 +157,9 @@ void GLYuvWidget::inittexture() glActiveTexture(GL_TEXTURE2); //激活纹理单元GL_TEXTURE2 glBindTexture(GL_TEXTURE_2D, m_idV); + glPixelStorei(GL_UNPACK_ROW_LENGTH, m_linesizeV); //使用内存中的数据创建真正的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_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -175,6 +168,7 @@ void GLYuvWidget::inittexture() void GLYuvWidget::paintGL() { + qDebug() << "paintGL()"; inittexture(); //指定y纹理要使用新值 glUniform1i(m_textureUniformY, 0); diff --git a/src/glyuvwidget.h b/src/glyuvwidget.h index c40b2e5..4ce03fe 100644 --- a/src/glyuvwidget.h +++ b/src/glyuvwidget.h @@ -18,7 +18,7 @@ public: public slots: //显示一帧Yuv图像 - void slotShowYuv(QByteArray buffer, uint width, uint height); + void slotShowYuv(quint8* bufferY, quint8* bufferU, quint8* bufferV, quint32 linesizeY, quint32 linesizeU, quint32 linesizeV); protected: void initializeGL() Q_DECL_OVERRIDE; @@ -45,11 +45,15 @@ private: GLuint m_idV = 0; // 视频宽高 - quint32 m_videoWidth; - quint32 m_videoHeight; + quint32 m_videoWidth = 1080; + quint32 m_videoHeight = 2160; - char *m_yuvPtr = Q_NULLPTR; - QByteArray m_buffer; + quint8* m_bufferY = Q_NULLPTR; + 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