H.264的码流封装格式
在H.264进行编码之后,生成的数据都封装为NAL Unit,多个NAL Unit串在一起形成总的输出码流。
-
Annex-B字节流格式:
大部分编码器的默认输出格式;
每个NAL Unit以规定格式的起始码分割;
起始码:0x 00 00 00 01 或 0x 00 00 01 -
RTP数据包格式:
直接封装NAL Unit,无起始码
每个NAL Unit之前以几个字节表示NAL Unit的长度
NAL Unit字节流格式
标准协议文档:“Annex B - Byte stream format”
NAL Unit提取方法
- 查找start_code_prefix之间的数据,是为一个NAL Unit的有效数据;
- 如: 00 00 00 01 67 42 00 1E E8 58 58 98 80 00 00 00 01 68 C8 …
- 该NAL Unit的实际内容为 67 42 00 1E E8 58 58 98 80
- start_code_prefix:0x00 00 00 01或0x 00 00 01
实践:从码流中读取NAL Unit
// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
typedef unsigned char uint8;
static int find_nal_prefix(ifstream& pfile,vector<uint8> &nalBytes) {
/*
00 00 00 01 x x x x x 00 00 00 01
*/
uint8 prefix[3] = { 0 };
/*
[0][1][2] = {0 0 0}-> [1][2][0]={0 0 0} -> [2][0][1]={0 0 0}->...
getc()=1
*/
nalBytes.clear();
uint8 x,pos=0;
int getprefix = 0;
for (int idx = 0; idx < 3; idx++) {
x = pfile.get();
prefix[idx] = x;
nalBytes.push_back(x);
}
while ((x = pfile.get()) != EOF) {
//cout << x << endl;
if (prefix[pos %3]==0&& prefix[(pos+1) % 3] == 0&& prefix[(pos + 2) % 3] == 1) {
//0x 00 00 01 found
getprefix = 1;
nalBytes.pop_back();
nalBytes.pop_back();
nalBytes.pop_back();
break;
}
else if (prefix[pos % 3] == 0 && prefix[(pos + 1) % 3] == 0 && prefix[(pos + 2) % 3] == 0) {
//0x 00 00 00 found
if (x == 1) {
//0x 00 00 00 01 found
getprefix = 2;
nalBytes.pop_back();
nalBytes.pop_back();
nalBytes.pop_back();
//nalBytes.pop_back(); 还没push
break;
}
}
else {
prefix[(pos++) % 3] = x;
nalBytes.push_back(x);
}
}
return getprefix;
}
//void Oc2Hex(int a){
// char buffer[33];
// sprintf_s(buffer, "%x", a);
// cout << buffer << endl;
//}
int main(int argc,char* argv[])
{
int *p1 = new int[10];
int *p2 = new int[10]();
ifstream inFile;
inFile.open(argv[1], ios::in | ios::binary);
if (!inFile) { //条件成立,则说明文件打开成功
cout << "Error:opening input file failed!" << endl;
return 0;
}
else
cout << "opening input file success!" << endl;
int x;
vector<uint8> nalBaytes;
auto ou = find_nal_prefix(inFile,nalBaytes);
ou = find_nal_prefix(inFile, nalBaytes);
for (auto i : nalBaytes)
printf("%x\t", i);
printf("\n");
ou = find_nal_prefix(inFile, nalBaytes);
for (auto i : nalBaytes)
printf("%x\t", i);
printf("\n");
ou = find_nal_prefix(inFile, nalBaytes);
for (auto i : nalBaytes)
printf("%x\t", i);
printf("\n");
inFile.close();
return 0;
}