h265 碼流分析幀類(lèi)型判斷

  • 分析下h265碼流(字節(jié)流模式),nal單元如何分割,類(lèi)型。
  • 先上一段h265的碼流片段
碼流數(shù)據(jù).jpg
  • nal單元分割
    尋找0x000001或者0x00000001, 規(guī)則如下:
    1. 每個(gè)NALU前面都有起始碼0x000001, 3bits
    2. 如果NALU類(lèi)型為vps, sps, pps, 或者解碼順序?yàn)榈谝粋€(gè)AU的第一個(gè)NALU, 起始碼前面再加一個(gè)0x00
    3. 視頻流的首個(gè)NALU的起始碼前加入0x00
      實(shí)際分析中,不必要整的這么復(fù)雜,只要找到0x000001或者0x00000001即可
  • 上圖中的碼流nal拆分為:
    第一幀:
    0000 0001 4001 0c01 ffff 0160 0000 0300 0003 0000 0300 0003 00ba 9702 40
    第二幀:
    00 0000 0142 0101 0160 0000 0300 0003 0000 0300 0003 00ba a00f 0804 47f9 65e4 91b6 1c5e 4924 fe79 fcf2 ffff ffcf e7f3 f3f9 d9
    第三幀:
    00 0000 0144 01c1 9095 8112
    第四幀:
    0000 0126 01af 1380 790b dc5c 557c 74...
  • NAL類(lèi)型分析
    類(lèi)型枚舉定義
enum NALUnitType {
    NAL_TRAIL_N    = 0,
    NAL_TRAIL_R    = 1,
    NAL_TSA_N      = 2,
    NAL_TSA_R      = 3,
    NAL_STSA_N     = 4,
    NAL_STSA_R     = 5,
    NAL_RADL_N     = 6,
    NAL_RADL_R     = 7,
    NAL_RASL_N     = 8,
    NAL_RASL_R     = 9,
    NAL_BLA_W_LP   = 16,
    NAL_BLA_W_RADL = 17,
    NAL_BLA_N_LP   = 18,
    NAL_IDR_W_RADL = 19,
    NAL_IDR_N_LP   = 20,
    NAL_CRA_NUT    = 21,
    NAL_VPS        = 32,
    NAL_SPS        = 33,
    NAL_PPS        = 34,
    NAL_AUD        = 35,
    NAL_EOS_NUT    = 36,
    NAL_EOB_NUT    = 37,
    NAL_FD_NUT     = 38,
    NAL_SEI_PREFIX = 39,
    NAL_SEI_SUFFIX = 40,
};

類(lèi)型判斷方式為分隔符之后的第一個(gè)字節(jié)右移一位的值
第一幀:0x40 >> 1 , 得到0x20,十進(jìn)制32,為NAL_VPS
第二幀:0x42 >> 1 , 得到0x21, 十進(jìn)制33, 為NAL_SPS
第三幀:0x44 >> 1 , 得到0x22, 十進(jìn)制34, 為NAL_PPS
第四幀:0x26 >> 1 , 得到0x13, 十進(jìn)制19, 為NAL_IDR_W_RADL

  • 代碼如下
static int hevc_probe(char* pbuf, int buf_size)
{
    unsigned int code = -1;
    int vps = 0, sps = 0, pps = 0, irap = 0;
    int i;
    
    for (i = 0; i < buf_size - 1; i++) {
        code = (code << 8) + pbuf[i];
        if ((code & 0xffffff00) == 0x100) {
            char nal2 = pbuf[i + 1];
            int type = (code & 0x7E) >> 1;
            
            if (code & 0x81) // forbidden and reserved zero bits
                return 0;
            
            if (nal2 & 0xf8) // reserved zero
                return 0;
            
            switch (type) {
                case NAL_VPS:        vps++;  break;
                case NAL_SPS:        sps++;  break;
                case NAL_PPS:        pps++;  break;
                case NAL_BLA_N_LP:
                case NAL_BLA_W_LP:
                case NAL_BLA_W_RADL:
                case NAL_CRA_NUT:
                case NAL_IDR_N_LP:
                case NAL_IDR_W_RADL: irap++; break;
            }
        }
    }
    
    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容