FFmpeg入门教程10.08:软解并使用QOpenGL播放视频(YUV420P)
系列索引:FFmpeg入门系列索引
上一篇:FFmpeg入门教程10.07:软解并使用QtWidget播放视频(YUV420P->RGB32)
我在开发过程中Qt用的比较大,所以本系列主要界面由Qt开发。而Qt主要的特性是跨平台,在嵌入式平台中,主要使用QML进行界面开发,如果使用QML开发视频的话,就需要用到OpenGL了。
本篇主要介绍常用的桌面版的QOpenGL的视频显示,桌面版解码的YUV数据格式为YUV420P,下一篇介绍QML版的视频显示,也是YUV420P格式的。
解码流程图为:
flowchart TB
F --Yes--> I
K --下一帧--> F
I --No--> F
subgraph init
direction TB
A(开始) --> B[打开文件]
B --> C[查找流信息]
C --> D[查找对应解码器]
D --> E[打开解码器]
E --> F{读取帧}
F --No--> G(结束)
end
subgraph decode
direction TB
I{是视频帧?} --Yes--> J[发送帧给解码器]
J --> K[从解码器获取结果]
end
flowchart TB
F --Yes--> I
K --Next Frame--> F
I --No--> F
subgraph init
direction TB
A(Start) --> B[avformat_open_input]
B --> C[av_find_stream_info]
C --> D[avcodec_find_decoder]
D --> E[avcodec_open]
E --> F{av_read_frame}
F --No--> G(End)
end
subgraph decode
direction TB
I{Video Packet?} --Yes--> J[avcodec_send_packet]
J --> K[avcodec_receive_frame]
end
Qt显示流程图:
flowchart TB
A(开始) --> B[initializalGL初始化QOpenGL]
B --> C[界面缩放resizeGL]
C --> D[纹理绘制paintGL]
D --> E(结束)
函数调用显示流程图为:
flowchart TB
K --signals/slots--> O
QOpenGLWidget --prompt--> QWidget
subgraph decode
direction TB
A(Start) --> B[avformat_open_input]
B --> C[av_find_stream_info]
C --> D[avcodec_find_decoder]
D --> E[avcodec_open]
E --> F{av_read_frame}
F --No--> G(End)
F --Yes--> H[avcodec_send_packet]
H --> I[avcodec_receive_frame]
I --> J[sws_scale]
J --> K[QImage]
end
subgraph QOpenGLWidget
direction TB
N[initGL]
O[paintGL]
L[resizeGL]
end
subgraph QWidget
M[QOpenGLWidget]
end
共分为三个部分。
第一部分:视频解码部分
这个就比较简单,前面几篇文章一直在说这个,FFmpeg默认软解输出格式为YUV420P。
这里需要注意的是解码之后的AVFrame处理。
YUV420P共有三个分量,即:Y、U、V。存储在三个数组中。
解码部分代码为:
1 |
|
将AVFrame三个分量数组的数据按照YUV420P的分量排列格式复制到out_buffer指针指向的内存中。然后发送信号给界面,通知界面一帧解码完成,可以刷新显示界面了。
第二部分:QOpenGL渲染纹理部分
在PC上使用QOpenGL绘制图像,需要继承QOpenGLWidget类,这样,类中的所有数据处理显示都会作用在界面上。
QOpenGLWidget类有三个重要的虚函数必须实现。
- void initializeGL();
- void resizeGL(int w,int h);
- void paintGL();
initializeGL函数由界面自动调用,并且只调用一次。resizeGL函数会在界面大小调整时自动调用,而paintGL函数绘制界面刷新时自动调用。
渲染代码为:
1 |
|
当解码类发送一帧解码完信号时,调用此类的update函数刷新界面。
此种方法在QML中不适用,推荐本工程提供的两种方法都看一下。
第三部分:MainWindow/Widget显示部分
不管是界面是QMainWindow还是QWidget类,要想显示QOpenGLWidget内容就需要界面类中有OpenGL Widget。
黑色部分即为OpenGL Widget组件,在右侧属性栏中可以看到openGLWidget的类为QOpenGLWidget。
点击右键提升为第二部分的渲染类I420Render。
可以看到类由QOpenGLWidget提升为I420Render2(这里有个2是因为有两种写法)。
编译运行,显示界面为:
点击Play
按钮后会自动打开解码播放显示视频。
问题
本文的效果和上一篇相比,亮度明显暗不少。
源码在ffmpeg_beginner中10.08.1video_decode_by_cpu_display_by_qopengl
、09.2video_decode_by_cpu_display_by_qopengl
下。可以查看两种写法不同的地方