天天看點

H264包解析

在H.264/AVC标準中,整個系統架構被分為了兩個層面:視訊編碼層面(VCL)和網絡抽象層面(NAL)。

VCL負責表示視訊資料的内容,NAL則負責格式化資料并提供頭資訊,以保證資料适合各種信道和存儲媒體上的傳輸。

在VCL資料傳輸或存儲之前,這些編碼的VCL資料,先被映射或封裝進NAL單元中。

NAL單元是NAL的基本文法結構,它包含一個位元組的頭資訊和一系列來自VCL的稱為原始位元組序列載荷的位元組流(RBSP)。

H264碼流結構圖:

H264包解析

起始碼:如果NALU對應的slice為一幀的開始,NAL則用4位元組表示,即0x00 00 00 01,負責用3位元組表示:0x00 00 01。

NAL Header:forbidden_bit,nal_reference_bit(優先級),nal_unit_type(類型)。

脫殼操作:為了使NALU主體不包括起始碼,在編碼時每遇到兩個位元組(連續)的0,就插入一位元組0x03,以和起始碼差別。

NAL單元解碼流程:

H264包解析

流程為:首先從NAL單元中提取出RBSP結構流,然後根據NALU類型處理RBSP資料。

從h264原檔案中分離出NAL資料,用c代碼的一種實作方式:

int FindStartCode (unsigned char *Buf, int zeros_in_startcode)
{
  int info;
  int i;

  info = 1;
  for (i = 0; i < zeros_in_startcode; i++)
    if(Buf[i] != 0)
      info = 0;

  if(Buf[i] != 1)
    info = 0;
  return info;
}
           
int getNextNal(FILE* inpf, unsigned char* Buf)//打開的檔案句柄,和将讀取的位元組存儲到Buf中
{
	int pos = 0;
	int StartCodeFound = 0;
	int info2 = 0;
	int info3 = 0;
	int i = 0;
	while (!feof(inpf) && (Buf[pos++] = fgetc(inpf)) == 0);//跳過NAL頭

<span style="white-space:pre">	</span>/*通過查找下一次的NAL頭來計算本次的NAL的長度,根據長度來讀取NAL資料包*/
	while (!StartCodeFound)
	{
		if (feof (inpf))
		{
			return pos-1;
		}
		Buf[pos++] = fgetc (inpf);
		printf("%02X\n", Buf[pos - 1]);
		info3 = FindStartCode(&Buf[pos-4], 3);
		if(info3 != 1)
			info2 = FindStartCode(&Buf[pos-3], 2);
		StartCodeFound = (info2 == 1 || info3 == 1);
	}
	fseek (inpf, -4, SEEK_CUR);
	return pos - 4;//傳回的就是一個NAL的長度
}
           

得到NAL就可以去做相應的解碼處理了。X264提供的僅是對于h264的編碼操作,FFMPEG有解碼的實作,具體的請看我的另一篇博文,