视频编解码学习(2):H264学习笔记

来源:互联网 发布:无损音乐 软件 编辑:程序博客网 时间:2024/05/22 15:56

RT


文章1:最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0)

http://blog.csdn.net/leixiaohua1020/article/details/38868499

文章2:最简单的基于FFmpeg的解码器-纯净版(不包含libavformat)

http://blog.csdn.net/leixiaohua1020/article/details/42181571


现在把我学习的重要内容总结一下:


在文章1里面,有一段代码:

int iFrameIndex = 1;    while( av_read_frame(pFormatCtx, packet) >= 0 ) {        m_mylog.LogFile(_T("Frame: %d, Size: %d"), iFrameIndex ++, packet->size);                if( packet->stream_index == videoindex ) {            ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);            if( ret < 0 ) {                printf("Decode Error.\n");                return -1;            }        }    }
这里会计算该文件有多少个Frame,我测试的结果为250,但这里仅贴出前10个Frame的结果。

DEBUG - Frame: 1, Size: 22572
DEBUG - Frame: 2, Size: 2803
DEBUG - Frame: 3, Size: 623
DEBUG - Frame: 4, Size: 495
DEBUG - Frame: 5, Size: 3730
DEBUG - Frame: 6, Size: 699
DEBUG - Frame: 7, Size: 635
DEBUG - Frame: 8, Size: 4056
DEBUG - Frame: 9, Size: 552
DEBUG - Frame: 10, Size: 613


同理在文章2里面,有一段代码:

    while( 1 ) {        //         cur_size = fread(in_buffer, 1, IN_BUFFER_SIZE, fp_in);        if( cur_size == 0 ) {            break;        }        cur_ptr = in_buffer;                while( cur_size > 0 ) {            // 解析获得一个Packet            int len = av_parser_parse2(                pCodecParserCtx, pCodecCtx,                &packet.data, &packet.size,                cur_ptr , cur_size ,                AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);                        cur_ptr += len;            cur_size -= len;                        if( packet.size == 0 ) {                continue;            }                        // decode this buffer            //Some Info from AVCodecParserContext            m_mylog.LogFile(_T("Index: %d Packet Size:%6d"), iPacketIndex ++, packet.size);            // ...        }
也是获取有多少个Frame的,不过使用的方法不一样。但是结果是相同的。


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 2015/7/22今天我好好的调试了一个h264文件,想要探索它究竟是什么?当然了,不可避免的需要学习新知识。

先给出几个自问自答。

1. h264是什么?

新一代高清视频编码格式

2. NALU是什么?

答:NALU头结构:NALU类型(5bit)、重要性指示位(2bit)、禁止位(1bit)

因为NALU在文件里面是二进制的,为了区分这些NALU,需要定义(0x00000001或者0x000001)来作为间隔符。

区别:如果NALU对应的Slice(Slice为P帧,也就是差别帧)为一帧的开始,则用4字节表示,即0x00000001;否则用3字节表示,0x000001。


参考:http://blog.csdn.net/wudebao5220150/article/details/13810671


3.如何解析h264 ?

为了解析h264,我先上传一个h264的文件ds.h264

该文件大小为:201,432 字节

3.1 使用ffmpeg解析h264文件

参考:http://blog.csdn.net/leixiaohua1020/article/details/38868499

首先使用FFMPEG里面的av_read_frame读取所有的帧,得到如下结果:
Frame: 1, Size: 9777Frame: 2, Size: 215Frame: 3, Size: 113Frame: 4, Size: 75Frame: 5, Size: 95Frame: 6, Size: 435Frame: 7, Size: 217Frame: 8, Size: 123Frame: 9, Size: 139Frame: 10, Size: 913Frame: 11, Size: 291Frame: 12, Size: 182Frame: 13, Size: 184Frame: 14, Size: 10118Frame: 15, Size: 1017Frame: 16, Size: 260Frame: 17, Size: 235Frame: 18, Size: 2773Frame: 19, Size: 509Frame: 20, Size: 340Frame: 21, Size: 361Frame: 22, Size: 5374Frame: 23, Size: 841Frame: 24, Size: 608Frame: 25, Size: 363Frame: 26, Size: 5233Frame: 27, Size: 1143Frame: 28, Size: 677Frame: 29, Size: 486Frame: 30, Size: 4918Frame: 31, Size: 1330Frame: 32, Size: 659Frame: 33, Size: 591Frame: 34, Size: 4944Frame: 35, Size: 1745Frame: 36, Size: 777Frame: 37, Size: 923Frame: 38, Size: 5555Frame: 39, Size: 1930Frame: 40, Size: 1037Frame: 41, Size: 1093Frame: 42, Size: 5735Frame: 43, Size: 2351Frame: 44, Size: 1296Frame: 45, Size: 1246Frame: 46, Size: 5268Frame: 47, Size: 2193Frame: 48, Size: 1142Frame: 49, Size: 1006Frame: 50, Size: 4657Frame: 51, Size: 2039Frame: 52, Size: 919Frame: 53, Size: 950Frame: 54, Size: 5293Frame: 55, Size: 2063Frame: 56, Size: 799Frame: 57, Size: 862Frame: 58, Size: 5294Frame: 59, Size: 1743Frame: 60, Size: 1136Frame: 61, Size: 890Frame: 62, Size: 5284Frame: 63, Size: 1902Frame: 64, Size: 920Frame: 65, Size: 962Frame: 66, Size: 5593Frame: 67, Size: 2280Frame: 68, Size: 1087Frame: 69, Size: 907Frame: 70, Size: 5525Frame: 71, Size: 2117Frame: 72, Size: 976Frame: 73, Size: 1202Frame: 74, Size: 5578Frame: 75, Size: 2170Frame: 76, Size: 981Frame: 77, Size: 951Frame: 78, Size: 5468Frame: 79, Size: 1555Frame: 80, Size: 1009Frame: 81, Size: 710Frame: 82, Size: 5009Frame: 83, Size: 1361Frame: 84, Size: 691Frame: 85, Size: 638Frame: 86, Size: 4953Frame: 87, Size: 1514Frame: 88, Size: 607Frame: 89, Size: 778Frame: 90, Size: 4590Frame: 91, Size: 1390Frame: 92, Size: 607Frame: 93, Size: 526Frame: 94, Size: 4905Frame: 95, Size: 1282Frame: 96, Size: 651Frame: 97, Size: 654Frame: 98, Size: 5477Frame: 99, Size: 2072Frame: 100, Size: 1069Total Frame Size: 201432
看到没有,正好是201432,这样一看,一共有100帧。但是还有其他问题,哪些是I帧,哪些是P帧?如何将这些帧通过RTP发送出去呢?这些帧在二进制的格式是什么?好,别急,现在只是FFMPEGE帮助我解析了这些帧,当然文件h264文件在手,我也可以自己解析这些帧。



3.2 全手工解析h264文件

参考:http://download.csdn.net/download/yechuanfei/4313339
将该文章里面的代码下载后,并仔细调试,我得到如下结果:
Index: 1 -- len: 24 -- prefix: 4 nal_unit_type: 7Index: 2 -- len: 5 -- prefix: 4 nal_unit_type: 8Index: 3 -- len: 698 -- prefix: 3 nal_unit_type: 6Index: 4 -- len: 9036 -- prefix: 3 nal_unit_type: 5Index: 5 -- len: 211 -- prefix: 4 nal_unit_type: 1Index: 6 -- len: 109 -- prefix: 4 nal_unit_type: 1Index: 7 -- len: 71 -- prefix: 4 nal_unit_type: 1Index: 8 -- len: 91 -- prefix: 4 nal_unit_type: 1Index: 9 -- len: 431 -- prefix: 4 nal_unit_type: 1Index: 10 -- len: 213 -- prefix: 4 nal_unit_type: 1Index: 11 -- len: 119 -- prefix: 4 nal_unit_type: 1Index: 12 -- len: 135 -- prefix: 4 nal_unit_type: 1Index: 13 -- len: 909 -- prefix: 4 nal_unit_type: 1Index: 14 -- len: 287 -- prefix: 4 nal_unit_type: 1Index: 15 -- len: 178 -- prefix: 4 nal_unit_type: 1Index: 16 -- len: 180 -- prefix: 4 nal_unit_type: 1Index: 17 -- len: 10114 -- prefix: 4 nal_unit_type: 1Index: 18 -- len: 1013 -- prefix: 4 nal_unit_type: 1Index: 19 -- len: 256 -- prefix: 4 nal_unit_type: 1Index: 20 -- len: 231 -- prefix: 4 nal_unit_type: 1Index: 21 -- len: 2769 -- prefix: 4 nal_unit_type: 1Index: 22 -- len: 505 -- prefix: 4 nal_unit_type: 1Index: 23 -- len: 336 -- prefix: 4 nal_unit_type: 1Index: 24 -- len: 357 -- prefix: 4 nal_unit_type: 1Index: 25 -- len: 5370 -- prefix: 4 nal_unit_type: 1Index: 26 -- len: 837 -- prefix: 4 nal_unit_type: 1Index: 27 -- len: 604 -- prefix: 4 nal_unit_type: 1Index: 28 -- len: 359 -- prefix: 4 nal_unit_type: 1Index: 29 -- len: 5229 -- prefix: 4 nal_unit_type: 1Index: 30 -- len: 1139 -- prefix: 4 nal_unit_type: 1Index: 31 -- len: 673 -- prefix: 4 nal_unit_type: 1Index: 32 -- len: 482 -- prefix: 4 nal_unit_type: 1Index: 33 -- len: 4914 -- prefix: 4 nal_unit_type: 1Index: 34 -- len: 1326 -- prefix: 4 nal_unit_type: 1Index: 35 -- len: 655 -- prefix: 4 nal_unit_type: 1Index: 36 -- len: 587 -- prefix: 4 nal_unit_type: 1Index: 37 -- len: 4940 -- prefix: 4 nal_unit_type: 1Index: 38 -- len: 1741 -- prefix: 4 nal_unit_type: 1Index: 39 -- len: 773 -- prefix: 4 nal_unit_type: 1Index: 40 -- len: 919 -- prefix: 4 nal_unit_type: 1Index: 41 -- len: 5551 -- prefix: 4 nal_unit_type: 1Index: 42 -- len: 1926 -- prefix: 4 nal_unit_type: 1Index: 43 -- len: 1033 -- prefix: 4 nal_unit_type: 1Index: 44 -- len: 1089 -- prefix: 4 nal_unit_type: 1Index: 45 -- len: 5731 -- prefix: 4 nal_unit_type: 1Index: 46 -- len: 2347 -- prefix: 4 nal_unit_type: 1Index: 47 -- len: 1292 -- prefix: 4 nal_unit_type: 1Index: 48 -- len: 1242 -- prefix: 4 nal_unit_type: 1Index: 49 -- len: 5264 -- prefix: 4 nal_unit_type: 1Index: 50 -- len: 2189 -- prefix: 4 nal_unit_type: 1Index: 51 -- len: 1138 -- prefix: 4 nal_unit_type: 1Index: 52 -- len: 1002 -- prefix: 4 nal_unit_type: 1Index: 53 -- len: 4653 -- prefix: 4 nal_unit_type: 1Index: 54 -- len: 2035 -- prefix: 4 nal_unit_type: 1Index: 55 -- len: 915 -- prefix: 4 nal_unit_type: 1Index: 56 -- len: 946 -- prefix: 4 nal_unit_type: 1Index: 57 -- len: 5289 -- prefix: 4 nal_unit_type: 1Index: 58 -- len: 2059 -- prefix: 4 nal_unit_type: 1Index: 59 -- len: 795 -- prefix: 4 nal_unit_type: 1Index: 60 -- len: 858 -- prefix: 4 nal_unit_type: 1Index: 61 -- len: 5290 -- prefix: 4 nal_unit_type: 1Index: 62 -- len: 1739 -- prefix: 4 nal_unit_type: 1Index: 63 -- len: 1132 -- prefix: 4 nal_unit_type: 1Index: 64 -- len: 886 -- prefix: 4 nal_unit_type: 1Index: 65 -- len: 5280 -- prefix: 4 nal_unit_type: 1Index: 66 -- len: 1898 -- prefix: 4 nal_unit_type: 1Index: 67 -- len: 916 -- prefix: 4 nal_unit_type: 1Index: 68 -- len: 958 -- prefix: 4 nal_unit_type: 1Index: 69 -- len: 5589 -- prefix: 4 nal_unit_type: 1Index: 70 -- len: 2276 -- prefix: 4 nal_unit_type: 1Index: 71 -- len: 1083 -- prefix: 4 nal_unit_type: 1Index: 72 -- len: 903 -- prefix: 4 nal_unit_type: 1Index: 73 -- len: 5521 -- prefix: 4 nal_unit_type: 1Index: 74 -- len: 2113 -- prefix: 4 nal_unit_type: 1Index: 75 -- len: 972 -- prefix: 4 nal_unit_type: 1Index: 76 -- len: 1198 -- prefix: 4 nal_unit_type: 1Index: 77 -- len: 5574 -- prefix: 4 nal_unit_type: 1Index: 78 -- len: 2166 -- prefix: 4 nal_unit_type: 1Index: 79 -- len: 977 -- prefix: 4 nal_unit_type: 1Index: 80 -- len: 947 -- prefix: 4 nal_unit_type: 1Index: 81 -- len: 5464 -- prefix: 4 nal_unit_type: 1Index: 82 -- len: 1551 -- prefix: 4 nal_unit_type: 1Index: 83 -- len: 1005 -- prefix: 4 nal_unit_type: 1Index: 84 -- len: 706 -- prefix: 4 nal_unit_type: 1Index: 85 -- len: 5005 -- prefix: 4 nal_unit_type: 1Index: 86 -- len: 1357 -- prefix: 4 nal_unit_type: 1Index: 87 -- len: 687 -- prefix: 4 nal_unit_type: 1Index: 88 -- len: 634 -- prefix: 4 nal_unit_type: 1Index: 89 -- len: 4949 -- prefix: 4 nal_unit_type: 1Index: 90 -- len: 1510 -- prefix: 4 nal_unit_type: 1Index: 91 -- len: 603 -- prefix: 4 nal_unit_type: 1Index: 92 -- len: 774 -- prefix: 4 nal_unit_type: 1Index: 93 -- len: 4586 -- prefix: 4 nal_unit_type: 1Index: 94 -- len: 1386 -- prefix: 4 nal_unit_type: 1Index: 95 -- len: 603 -- prefix: 4 nal_unit_type: 1Index: 96 -- len: 522 -- prefix: 4 nal_unit_type: 1Index: 97 -- len: 4901 -- prefix: 4 nal_unit_type: 1Index: 98 -- len: 1278 -- prefix: 4 nal_unit_type: 1Index: 99 -- len: 647 -- prefix: 4 nal_unit_type: 1Index: 100 -- len: 650 -- prefix: 4 nal_unit_type: 1Index: 101 -- len: 5473 -- prefix: 4 nal_unit_type: 1Index: 102 -- len: 2068 -- prefix: 4 nal_unit_type: 1Index: 103 -- len: 1065 -- prefix: 4 nal_unit_type: 1Total is : 201432
看到没,恰好也是201432个字节。
这里的 prefix为4表明其值为0x00000001,prefix为3表明其值为0x000001。

nal_unit_type的含义见如下结构体:
//H264定义的类型 values for nal_unit_typetypedef enum {    NALU_TYPE_SLICE     = 1, //P 帧    NALU_TYPE_DPA      = 2,    NALU_TYPE_DPB      = 3,    NALU_TYPE_DPC      = 4,    NALU_TYPE_IDR      = 5, // I帧    NALU_TYPE_SEI      = 6, // 补充增强信息    NALU_TYPE_SPS      = 7, // 序列参数集Sequence Parameter Set    NALU_TYPE_PPS      = 8, // 图像参数集Picture Parameter Set    NALU_TYPE_AUD      = 9,    NALU_TYPE_EOSEQ     = 10,    NALU_TYPE_EOSTREAM    = 11,    NALU_TYPE_FILL      = 12,#if (MVC_EXTENSION_ENABLE)    NALU_TYPE_PREFIX    = 14,    NALU_TYPE_SUB_SPS   = 15,    NALU_TYPE_SLC_EXT   = 20,    NALU_TYPE_VDRD     = 24  // View and Dependency Representation Delimiter NAL Unit#endif} NaluType;
具体的对比一下就可以知道了。


ffmpeg解析的帧 & 全手工解析的帧

对于第一个关键帧而言:


ffmpeg解析全手工解析
Frame: 1, Size: 9777
Index: 1 -- len: 24 -- prefix: 4 nal_unit_type: 7Index: 2 -- len: 5 -- prefix: 4 nal_unit_type: 8Index: 3 -- len: 698 -- prefix: 3 nal_unit_type: 6Index: 4 -- len: 9036 -- prefix: 3 nal_unit_type: 5
<pre name="code" class="cpp">Frame: 100, Size: 1069
Index: 103 -- len: 1065 -- prefix: 4 nal_unit_type: 1

ffmpeg解析的一个帧包含的信息可不少,包括7(序列参数集), 8(图像参数集), 6(补充增强信息), 5(I帧,即关键帧)的内容以及他们的前缀(即NALU的间隔)长。
而其他的帧就是P帧了,同样的ffmepg解析的帧 等于 真实的帧内容加上 NALU的间隔。

播放该h264文件

a. 新建一个w.sdp文件,内容如下:
m=video 5234 RTP/AVP 96a=rtpmap:96 H264a=framerate:25c=IN IP4 172.30.191.2
172.30.191.2是流媒体播放器接收的地址,5234是RTP接收流媒体的端口

b. 执行ffplay.exe w.sdp 或者 VLC media player打开w.sdp均可以

c. 使用3.2参考中下载的代码播放就可以了








0 0
原创粉丝点击