MPEG4基礎知識簡介以及 判斷MPEG4的I, P, B幀

基礎知識參看 : 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流的分析和它的IPB Frame的判定方法在這裏簡要記錄一下吧,供日後的翻看和大家的參考。!

 

MPEG4分析:

0x00, 0x00, 0x01, 0xB0作爲一個VOS的開始;

0x00, 0x00, 0x01, 0xB6作爲一個VOP的開始,緊跟着VOP開始的,有一個2bit 的標誌,用來表示這個Frame到底是一個 I FrameP FrameB Frame抑或是S FrameGMS-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)

              {

                     //判定是IPB ,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/VOPStartCode

              poslast=pos;

              pos=pos+4;   

       }

今天就把MPEG4流的分析和它的IPB Frame的判定方法在這裏簡要記錄一下吧,供日後的翻看和大家的參考。!

 

MPEG4分析:

0x00, 0x00, 0x01, 0xB0作爲一個VOS的開始;

0x00, 0x00, 0x01, 0xB6作爲一個VOP的開始,緊跟着VOP開始的,有一個2bit 的標誌,用來表示這個Frame到底是一個 I FrameP FrameB Frame抑或是S FrameGMS-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)

              {

                     //判定是IPB ,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/VOPStartCode

              poslast=pos;

              pos=pos+4;   

       }

發佈了58 篇原創文章 · 獲贊 8 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章