基礎知識參看 : http://www.docin.com/p-367796495.html
當用一副圖像來作爲一個VO的時候,VOP就對應於具體某一幀了,因爲VOP是VO特定時間點的表現
mpeg-4提出了視頻對象(Video Object )的概念,將一幅圖像分爲幾個視頻對象。例如一幅圖像中,人物作爲一個對象,背景爲另一個對象。VOP(Video Object Plant )-視頻對象平面,是一個VO的時間採樣。但是實際的編碼器中,還是將整個圖像作爲一個對象處理,這樣VOP就與以往幀的概念完全相同。P幀,即前向參考幀,是以當前幀之前的I、P幀爲參考幀的編碼圖像。B幀,雙向參考幀,以當前幀之前和之後的圖像幀爲參考幀的編碼圖像。而一個gov是由一個由i幀開始的,若干P、B幀組成的一個圖像組,具體包含多少幀圖像,由相關的編碼器參數決定。
今天就把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; //判斷是否是VOS頭;
if(addrp[pos]
== 0x00)
if(addrp[pos
+ 1] == 0x00)
if(addrp[pos
+ 2] == 0x01)
if(addrp[pos
+ 3] == 0xB6)
break; //判斷是否是VOP頭
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) //pos爲文件當前指針
{
length=pos-poslast+header; //每幀長度爲兩個StartCode之間的字節數;
if
(length
{
//長度小於一定值,則不夠一幀大小,表示在I
frame前面的VOS,VO,VOL頭
header=length;
}
else
{
header=0;
if
(0==(nInput=fread(buffer,1,length,fp))) break; //讀取一幀大小數據,
//調用解碼器接口,進行解碼測試操作;……
}
}
if
(p==NULL) break;
//判定VOS是哪種profile
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)
{
//判定是I,P,B
,S Frame
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++);
}
//繼續查找下一個VOS/VOP的StartCode
poslast=pos;
pos=pos+4;
}
今天就把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; //判斷是否是VOS頭;
if(addrp[pos]
== 0x00)
if(addrp[pos
+ 1] == 0x00)
if(addrp[pos
+ 2] == 0x01)
if(addrp[pos
+ 3] == 0xB6)
break; //判斷是否是VOP頭
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) //pos爲文件當前指針
{
length=pos-poslast+header; //每幀長度爲兩個StartCode之間的字節數;
if
(length
{
//長度小於一定值,則不夠一幀大小,表示在I
frame前面的VOS,VO,VOL頭
header=length;
}
else
{
header=0;
if
(0==(nInput=fread(buffer,1,length,fp))) break; //讀取一幀大小數據,
//調用解碼器接口,進行解碼測試操作;……
}
}
if
(p==NULL) break;
//判定VOS是哪種profile
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)
{
//判定是I,P,B
,S Frame
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++);
}
//繼續查找下一個VOS/VOP的StartCode
poslast=pos;
pos=pos+4;
}