把MPEG4码流的分析和它的I,P,B Frame的判定方法在这里简要记录一下吧,供日后的翻看和大家的参考。
测试解码器测试了很久,由于需要将H264和MPEG4的码流进行分析和判断,并逐帧输入解码器进行测试,如何正确的分析码流,并将Video送给我们的解码器做Decode的呢?耐着性子找了很多资料,主要也因为我本身对MPEG4和H264的码流的格式并不懂,自己在视频编码方面的积累也实在是太少了,所以也确实挺头疼的。后来就直接在网上找是否有对码流的各个部分意义的解释,开始搜索码流中的的StartCode。高兴的是,最终找到了一些有用的讯息,得以继续进行测试代码的撰写。
今天就把MPEG4码流的分析和它的I,P,B Frame的判定方法在这里简要记录一下吧,供日后的翻看和大家的参考。!
MPEG4码流分析:
0x00, 0x00, 0x01, 0xB0作为一个VOS的开始;
0x00, 0x00, 0x01, 0xB6作为一个VOP的开始,紧跟着VOP开始的,有一个2bit 的标志,用来表示这个Frame到底是一个 I Frame,P Frame,B Frame抑或是S Frame(GMS-VOP)
标志如下:
00: I Frame
01: P Frame
10: B Frame
11: S Frame
但是,有关这 2bit 是在0xB6的后面字节的高位还是低位,却没有很明确的描述。
于是又回头开始针对某个MPEG4编码好的文件开始分析,结果终于发现,判定方法如下:
1.可以写一个判定VOP,或者VOS开头的函数:
- static unsigned char *Find_VOP_Start(unsigned char *addrp, unsigned int FindSizes)
- {
- while(pos < FindSizes)
- {
- if(addrp[pos] == 0x00)
- if(addrp[pos + 1] == 0x00)
- if(addrp[pos + 2] == 0x01)
- if(addrp[pos + 3] == 0xB0)
- break;
- if(addrp[pos] == 0x00)
- if(addrp[pos + 1] == 0x00)
- if(addrp[pos + 2] == 0x01)
- if(addrp[pos + 3] == 0xB6)
- break;
- pos++;
- }
- if(pos< FindSizes - 4)
- {
- return addrp+pos+4;
- }
- else
- return NULL;
- }
2. 读一个MPEG4码流文件,然后利用刚才写的函数搜索StartCode:
- size_t nRead = fread(lpSrc, 1, lSize, fp);
- fseek(fp, 0, SEEK_SET);
- while (!feof(fp))
- {
- unsigned char *p=Find_VOP_Start(lpSrc,lSize);
- if (pos)
- {
- length=pos-poslast+header;
- if (length<MAX_HEADERLEN)
- {
- header=length;
- }
- else
- {
- header=0;
- if (0==(nInput=fread(buffer,1,length,fp))) break;
- }
- }
- if (p==NULL) break;
- if (*(p-1)==0xB0)
- {
- if (*p==0xF5) printf("VOS Header start,Advanced Simple Profile level 5!/n");
- else if (*p==0x1) printf("VOS Header start,Simple Profile level 1!/n");
- else if (*p==0x2) printf("VOS Header start,Simple Profile level 2/n!");
- ……
- else printf("VOS Header Start,Other profile@level/n!");
- }
- if (*(p-1)==0xB6)
- {
- if ((*p & 0xC0)==0x00)printf("VOP-I frame # %d, ", frames++);
- else if ((*p & 0xC0)==0x40) printf("VOP-P frame # %d, ", frames++);
- else if ((*p & 0xC0)==0x80) printf("VOP-B frame # %d, ", frames++);
- else if ((*p & 0xC0)==0xC0) printf("VOP-S frame # %d, ", frames++);
- else printf("VOP-unknown type frame # %d, ",frames++);
- }
- poslast=pos;
- pos=pos+4;
- }
可以简单拿个图说明一下,下图中,第一个VOS的开头,第二个是一个I Frame:
by lydia
(axdc_qa_team)
|