现在,我们已经简单的掌握了h.264数据的结构。是时候干点什么了,那就先来写一个H.264视频播放器吧。。
前面我们开发视频播放器的时候是通过:
avformat_open_input打开视频文件,然后再调用av_read_frame就可以读到一帧帧的数据了,
当然用这样的方法也可以直接打开并读取一个h.264文件,但是这样就违背了我们的初衷了,我们的目的是对上一节《H264数据格式讲解》的实践,因此我们采用C语言的文件操作直接读取文件然后再解析。
一个H264播放器的实现步骤大致如下:
一、从H.264文件中获取一个NALU
从上节可以知道,h264的NALU直接是用帧头(0x00000001或0x000001)隔开的,因此我们就逐个字节搜索,直到遇到h264的帧头,2个帧头之间的数据就是一个Nalu,既视为获取到了一帧h264视频数据。
查找一个nalu数据的代码大致如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
|
二、使用ffmpeg解码上面获取到的NALU
1.h264解码器初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
2.解码并转成rgb32
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
|
三、使用Qt显示图像
直接用QImage加载得到的rgb32数据即可:
1 2 3 4 5 |
|
然后在主线程显示出这个QImage即可。
四、播放速度控制
由于H264数据里面没有包含时间戳信息,因此只能根据帧率来做同步,举个栗子:比如视频帧率是15那么我们就每秒钟播放15张图像,既在显示完一帧图像后,延时(1000/15)毫秒,当然严格来说这个延时不大合理,因为他没有考虑解码消耗的时间,但我们不管他,有兴趣的自己去完善修改。
另外需要注意的是:视频帧率是在h264的Nalu数据里面的,因此需要成功解码一帧图像后才能获取到帧率信息。
主要代码大致如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
|
至此,一个完整的h264播放器就完成了。
H264测试文件下载地址:https://download.csdn.net/download/qq214517703/10422777
完整工程下载地址:https://download.csdn.net/download/qq214517703/10423384
======Bug修复 Begin =======
2019-01-18更新:
1.修复部分h264文件,一帧存在多个slice,播放花屏的问题。
下载地址:https://download.csdn.net/download/qq214517703/10924057
====== End =======
2019-10-24更新:
1.更新为ffmpeg4.1,同时支持播放h265。
下载地址:https://download.csdn.net/download/qq214517703/11914710
Github地址:https://github.com/yundiantech/FFMPEG_DEMO/tree/master/source/VideoDecode
音视频技术交流讨论欢迎加 QQ群 121376426