2012年8月14日 星期二

H.264 Elementary Stream 格式解析

格式詳述在 ISO 14996-10 (Annex B)和 rfc3984
00 00 00 01 67   
前五個byte 為 NAL Unit

bit 1  -- forbidden zero, 必須為0
bit 2-3  nal_ref_idc
bit 3-8 nal unit type


42 00 29 F4 02 80 2D 88 00 00 00
後面11個byte 為 sequence parameter set

00 00 00 01 68 CE 0B C8
再後面8個byte 為 picture parameter set

註: 要研究H.264 elementary stream 格式的話
有個 stream analyzer 會比較好用

可以試試 Elecard Stream Analyzer Demo ( Elecard StreamEye Studio)

http://www.rosoo.net/a/200912/8056.html

NAL 的格式在 14496-10  7.3
http://www.360doc.com/content/09/0429/11/59579_3309616.shtml

RBSP 是 Raw Byte Sequence Payload 的縮寫

以一段 H.264 Elementary Stream 來舉例
其架構如下
 SPS (Sequence Parameter Set, 00 00 00 01 67 ...) -->
PPS ( Picture Parameter Set, 00 00 00 01 68 ... ) -->
H.264 I Slice ( 00 00 00 01 65 )  -->
H.264 P Slice ( 00 00 00 01 41 )


I Slice ( 00 00 00 01 65, Unit Type 5 ) 是
Coded slice of an IDR picture, slice_layer_without_partitioning_rbsp( )
P Slice ( 00 00 00 01 41, Unit Type 1 ) 是

Coded slice of a non-IDR picture, slice_layer_without_partitioning_rbsp( )



instantaneous decoding refresh (IDR) picture: A coded picture containing only slices with I or SI slice types
that causes the decoding process to mark all reference pictures as "unused for reference" immediately after
decoding the IDR picture. After the decoding of an IDR picture all following coded pictures in decoding order
can be decoded without inter prediction from any picture decoded prior to the IDR picture. The first picture of
each coded video sequence is an IDR picture.



H264 Sequence Parameter Set  by Elecard Stream Analyzer

profile_idc = 66
constraint_set0_flag = 0
constraint_set1_flag = 0
constraint_set2_flag = 0
constraint_set3_flag = 0
reserved_zero_4bits = 0
level_idc = 41
seq_parameter_set_id = 0
log2_max_frame_num_minus4 = 0
pic_order_cnt_type = 0
     log2_max_pic_order_cnt_lsb_minus4 = 0
num_ref_frames = 1
gap


Useful info:
要把 little endian 轉 big endian 在VC 可以用
_byteswap_ulong
http://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c

使用 libmp4v2

出現 error

[h264 @ 0xd39480]non-existing PPS 0 referenced
[h264 @ 0xd39480]decode_slice_header error
[h264 @ 0xd39480]no frame!


根據以上提示以及跟正常 mp4 比對後
發現在 avcc 中沒有 PPS ( Picture Parameter Sequence )
在加上 MP4AddH264SequenceParameterSet()
及 MP4AddH264PictureParameterSet() 後 就可以正常播放

avcc 格式
01 42 00 29 FF E1 00 0C 67 42 00 29 F4 02 80 2D 88 00 00 00
01 00 04 68 CE 0B C8


aligned(8) class AVCDecoderConfigurationRecord {
unsigned int(8) configurationVersion = 1;
unsigned int(8) AVCProfileIndication;
unsigned int(8) profile_compatibility;
unsigned int(8) AVCLevelIndication;
bit(6) reserved = ‘111111’b;
unsigned int(2) lengthSizeMinusOne;
bit(3) reserved = ‘111’b;
unsigned int(5) numOfSequenceParameterSets;
for (i=0; i< numOfSequenceParameterSets; i++) {
unsigned int(16) sequenceParameterSetLength ;
bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;
}
unsigned int(8) numOfPictureParameterSets;
for (i=0; i< numOfPictureParameterSets; i++) {
unsigned int(16) pictureParameterSetLength;
bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;
}
}


good MP4 article
http://www.cnblogs.com/haibindev/archive/2011/10/17/2214518.html


AAC 解碼 & mux

要查14496-3 subpart 4
還有 13818-7

raw_data_block() 在

Table 12

raw_data_block()
{
while ((id = id_syn_ele) != ID_END) { 3 uimsbf
switch (id) {
case ID_SCE: single_channel_element();
break;
case ID_CPE: channel_pair_element();
break;
case ID_CCE: coupling_channel_element();
break;
case ID_LFE: lfe_channel_element();
break;
case ID_DSE: data_stream_element();
break;
case ID_PCE: program_config_element();
break;
case ID_FIL: fill_element();
}
}
byte_alignment();
}

Table 36

Table 36 – Syntaxtic element identification
ID name encoding Abbreviation Syntactic Element
ID_SCE 0x0 SCE single_channel_element()
ID_CPE 0x1 CPE channel_pair_element()
ID_CCE 0x2 CCE coupling_channel_element()
ID_LFE 0x3 LFE lfe_channel_element()
ID_DSE 0x4 DSE data_stream_element()
ID_PCE 0x5 PCE program_config_element()
ID_FIL 0x6 FIL fill_element()
ID_END 0x7 TERM



channel_pair_element()
{
element_instance_tag; 4 uimsbf
common_window; 1 uimsbf
if ( common_window ) {
ics_info();
ms_mask_present; 2 uimsbf
if (ms_mask_present == 1) {
for (g = 0; g < num_window_groups; g++) {
for (sfb = 0; sfb < max_sfb; sfb++) {
ms_used[g][sfb]; 1 uimsbf
}
}
}
}
individual_channel_stream(common_window);
individual_channel_stream(common_window);
}


Data Example
前三個都是 0x21 0x4F 0xFE

http://honwsn.itpub.net/post/41648/497237

http://mp4tech.net/document/audiocomp/0000207.asp


上例中有2个mdat,一个是视频内容、另一个音频内容。对于h264, aac编码的媒体来说,其视频mdat中内容是nal,对于音频来说,其内容为aac的一帧。mdat中的帧依次存放,每个帧的位置、时间、长度都由moov中的信息指定。可以看出,mdat是很好组建的,这种Box只含有数据。
http://blog.csdn.net/iamshaofa/article/details/7859244
http://blog.csdn.net/yukuilongqq/article/details/7732009



2012年8月13日 星期一

AVCDecoderConfigurationRecord


AVCDecoderConfigurationRecord


14496-15
aligned(8) class AVCDecoderConfigurationRecord {
unsigned int(8) configurationVersion = 1;
unsigned int(8) AVCProfileIndication;
unsigned int(8) profile_compatibility;
unsigned int(8) AVCLevelIndication;
bit(6) reserved = ‘111111’b;
unsigned int(2) lengthSizeMinusOne;
bit(3) reserved = ‘111’b;
unsigned int(5) numOfSequenceParameterSets;
for (i=0; i< numOfSequenceParameterSets; i++) {
unsigned int(16) sequenceParameterSetLength ;
bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;
}
unsigned int(8) numOfPictureParameterSets;
for (i=0; i< numOfPictureParameterSets; i++) {
unsigned int(16) pictureParameterSetLength;
bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;
}
}

其中 AVCProfileIndication 要查 14496-10
profile_idc
Base Profile 為  66  ( 0x42)
Main Profile 為 77  (0x4D)
Extended Profile 為 88 (0x58)


Level 0x29 為 41 ==> 4.1