1、ANNEXB格式AnnexB格式:NALU数据+开始前缀(00000001或000001,此处注意为甚么是4bit或3bit,后面有描述);针对H.320电话会议RTP格式:NALU数据+20个字节的类似的并不符合RTP协议的RTP头。针对IP网络的RTP打包方式H.264协议只规定了字节流格式,没有规定RTP格式。可能也是因为这个原因,JM的RTP格式没有被用到任何场合场合中,成为了摆设。下图中的RTP格式是h.264乐园的firstime从JM86中分析出来的。实际包交换网络中必须按照RFC3984将NALU数据封装为RTP包,而不能使用JM的RTP格式。下面引自“QUESTIONMARK
2、”的博客下面说明3字节起始码和4字节起始码。以下和leading_zero_8bits、trailing_zero_8bits已无关系,忘掉。if(next_bits(24)!=0x000001)zero_bytef(8)start_code_prefix_one_3bytesf(24)根据B.1节,可以看到所谓的4字节起始码是(zero_byte+3字节起始码)。那么看zero_byte的说明,就可以明白zero_byte什么时候出现,也就能明白什么时候出现4字节起始码:1.SPS、PPSnalu是4字节起始码;2.AccessUnit的首个nalu是4字节起始码(参见7.4.1.2.3)。
3、这里举个例子说明,用JM可以生成这样一段码流(不要使用JM8.6,它在这部分与标准不符),这个码流可以见本楼附件:SPS(4字节头)PPS(4字节头)SEI(4字节头)I0(slice0)(4字节头)I0(slice1)(3字节头)P1(slice0)(4字节头)P1(slice1)(3字节头)P2(slice0)(4字节头)P2(slice1)(3字节头)I0(slice0)是序列第一帧(I帧)的第一个slice,是当前AccessUnit的首个nalu,所以是4字节头。而I0(slice1)表示第一帧的第二个slice,所以是3字节头。P1(slice0)、P1(slice1)同理。总结:
4、1附录B字节流在一个byte_stream_nal_unit的前后可能出现若干个0x00,仅用作填充之用。这个不常见。24字节头只出现在SPS、PPS和7.4.1.2.3规定的AccessUnit的首个nalu。其余情况都是3字节头一共有两种起始码:3字节的0x000001和4字节的0x000000013字节的0x000001只有一种场合下使用,就是一个完整的帧被编为多个slice的时候,包含这些slice的nalu使用3字节起始码。其余场合都是4字节的。NAL层处理简析(2010-06-0916:00:34)转载标签:nal层nal杂谈分类:H.264NAL(NetworkAbstracti
5、onLayer)基本上可分两种:1,以有序字节流方式传送的针对H.320的;2,针对IP网络的RTP打包方式的。NAL作用:specifiedtoformatthatdataandprovideheaderinformationinamannerappropriateforconveyanceonavarietyofcommunicationchannelsorstoragemedia.NAL的处理过程基本上分为两步:1,将VCL层输出的SODB封装成nal_unit.Nal_unit是一个通用封装格式,可以适用于有序字节流方式和IP包交换方式。2,针对不同的传送网络(电路交换|包交换),将n
6、al_unit封装成针对不同网络的封装格式。第一步的具体过程:VCL层输出的比特流SODB(StringOfDataBits),到nal_unit之间,经过了以下三步处理:1,SODB字节对齐处理后封装成RBSP(RawByteSequencePayload)。2,为防止RBSP的字节流与有序字节流传送方式下的SCP(start_code_prefix_one_3bytes,0x000001)出现字节竞争情形,循环检测RBSP前三个字节,在出现字节竞争时在第三字节前加入emulation_prevention_three_byte(0x03),具体方法:nal_unit(NumBytesInN
7、ALunit)forbidden_zero_bitnal_ref_idcnal_unit_typeNumBytesInRBSP=0for(i=1;iNumBytesInNALunit;i+)if(i+20x000003000x0000010x000003010x0000020x000003020x0000030x00000303附上h.264解码nalu中检测起始码的算法流程for(;)ifnext24bitsare0x000001startCodeFound=truebreak;elseflush8bits/for(;)if(true=startCodeFound)/startcodefou
8、nd/Flushthestartcodefoundflush24bits/Nownavigateuptonextstartcodeandputtheinbetweenstuff/inthenalstructure.for(;)getnext24bits&checkifitequalsto0x000001if(false=(next24bits=000001)/searchforpattern0x000000checkifnext24bitsare0x000000if(false=result)/copythebyteintothebuffercopyonebytetotheNalunitels
9、ebreak;elsebreak;/for(;)2.MPEG4起始码MPEG4的特色是VOP,没有NALU的概念,仍使用startcode对每帧进行分界。MPEG4的起始码是0x000001.另外MPEG4中很多起始码也很有用,比如video_object_sequence_start_code0x000001B0表示一个视频对象序列的开始,VO_start_code0x000001B6表示一个VOP的开始.0x000001B6之后的两位,是00表示Iframe,01表示Pframe,10表示Bframe.SODB数据比特串最原始的编码数据RBSP原始字节序列载荷在SODB的后面填加了结尾比特
10、(RBSPtrailingbits一个bit“1”)若干比特“0”,以便字节对齐。EBSP扩展字节序列载荷-在RBSP基础上填加了仿校验字节(0X03)它的原因是:在NALU加到Annexb上时,需要填加每组NALU之前的开始码StartCodePrefix,如果该NALU对应的slice为一帧的开始则用4位字节表示,ox00000001,否则用3位字节表示ox000001.为了使NALU主体中不包括与开始码相冲突的,在编码时,每遇到两个字节连续为0,就插入一个字节的0x03。解码时将0x03去掉。也称为脱壳操作。网上查询的区别:在对整帧图像的数据比特串(SODB)添加原始字节序列载荷(RBS
11、P)结尾比特(RBSPtrailingbits,添加一比特的“1”和若干比特“0”,以便字节对齐)后,再检查RBSP中是否存在连续的三字节“0000000000000000000000xx”;若存在这种连续的三字节码,在第三字节前插入一字节的“003”,以免与起始码竞争,形成EBSP码流,这需要将近两倍的整帧图像码流大小。为了减小存储器需求,在每个宏块编码结束后即检查该宏块SODB中的起始码竞争问题,并保留SODB最后两字节的零字节个数,以便与下一宏块的SODB的开始字节形成连续的起始码竞争检测;对一帧图像的最后一个宏块,先添加结尾停止比特,再检测起始码竞争。本文来自CSDN博客,转载请标明出
12、处:typedefstructintbyte_pos;/!currentpositioninbitstream;intbits_to_go;/!currentbitcounterbytebyte_buf;/!currentbufferforlastwrittenbyteintstored_byte_pos;/!storageforpositioninbitstream;intstored_bits_to_go;/!storageforbitcounterbytestored_byte_buf;/!storageforbufferoflastwrittenbytebytebyte_buf_ski
13、p;/!currentbufferforlastwrittenbyteintbyte_pos_skip;/!storageforpositioninbitstream;intbits_to_go_skip;/!storageforbitcounterbyte*streamBuffer;/!actualbufferforwrittenbytesintwrite_flag;/!byte_bufbyte_buf|=1;/在尾部填一个“1”占1bitcurrStream-bits_to_go-;currStream-byte_bufbits_to_go;currStream-streamBufferc
14、urrStream-byte_pos+=currStream-byte_buf;currStream-bits_to_go=8;currStream-byte_buf=0;intRBSPtoEBSP(byte*streamBuffer,intbegin_bytepos,intend_bytepos,intmin_num_bytes)inti,j,count;for(i=begin_bytepos;iend_bytepos;i+)NAL_Payload_bufferi=streamBufferi;count=0;j=begin_bytepos;for(i=begin_bytepos;iend_b
15、ytepos;i+)if(count=ZEROBYTES_SHORTSTARTCODE&!(NAL_Payload_bufferi&0xFC)streamBufferj=0x03;j+;count=0;streamBufferj=NAL_Payload_bufferi;if(NAL_Payload_bufferi=0x00)count+;elsecount=0;j+;while(jbit_use_stuffingBitsimg-type+=16;returnj;在2010-6-915:33:33我又看到了别人博客上的一句话更加深了我的理解,这里贴出来。感谢QuestionMark标准7.4.1
16、.1如是说:ThisprocesscanallowanySODBtoberepresentedinaNALunitwhileensuringthatnosequenceof8zero-valuedbitsfollowedbyastartcodeprefix,regardlessofbyte-alignment,isemulatedwithintheNALunit.这段的意思是在nal_unit层面,即naluheader+RBSP的结构中,不可能出现0x000001这样的片段。这是通过SODB-RBSP-EBSP的过程中添加防冲突字节实现的。这里多说一句标准附录B如是说:anybytesequ
17、alto0x00thatfollowaNALunitsyntaxstructureandprecedethefour-bytesequence0x00000001(whichistobeinterpretedasazero_bytefollowedbyastart_code_prefix_one_3bytes)willbeconsideredtobetrailing_zero_8bitssyntaxelementsthatarepartoftheprecedingbytestreamNALunit.这一段则在说明byte_stream_nal_unit层面。结合B.1,可以明白这段话的意思是一个nalu之后,下一个起始码0x00000001之前,可能会有若干0x00,就是所谓的trailing_zero_8bits。此外B.1中还说明了在码流的最开始,还有可能有若干0x00,就是所谓的leading_zero_8bits。这些leading_zero_8bits和trailing_zero_8bits可能与传输打包有关,但在实际中,我没有见过包含这种“多余”的0x00的码流。
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2