如何根據 NALU 裸流資料來判斷其是 H.264 還是 H.265 編碼?丨有問有答

語言: CN / TW / HK

前一些時間,我在知識星球上建立了一個音視訊技術社群: 關鍵幀的音視訊開發圈 ,不少朋友加入並在裡面諮詢一些音視訊相關的技術問題,其中不乏一些開發中普遍遇到的問題,這裡我會挑一些放出來供大家參考。

今天我們要討論的問題是一位社群的朋友遇到的一個工作中的技術問題,原文如下:

請問如何根據推送過來的 NALU 裸流資料來判斷其是 H.264 編碼還是 H.265 編碼,然後根據判斷得到的編碼方式進行對應的解碼處理?

以下是回答,歡迎大家留言討論補充:

這是個很好的問題,謝謝你的提問。在這裡我分兩部分說明一下這個問題。

1)通常在處理音視訊資料時,我們如何選擇解碼器?

通常我們不是根據 NALU 裸流資料中的資訊來選擇解碼器,而是根據媒體封裝層的資訊來確定解碼器。

媒體封裝層是表示媒體資料是什麼封裝格式的,比如 MP4、FLV。在這層資訊裡,通常會攜帶碼流編碼格式的資訊。

拿 MP4 來說,我們可以根據 Sample Description Box(moov/trak/mdia/minf/stbl/stsd) 中的資訊來確定其封裝的碼流的編碼格式。參考:《MP4 格式》。

對於 FLV,我們可以根據 VideoTagHeader 中的 CodecID 等資訊來確定其封裝的碼流的編碼格式。參考:《FLV 格式》。

這樣的好處是效率比較高,解封裝的時候就可以確定選擇何種解碼器了。

2)怎麼識別 NALU 裸流資料的編碼格式是 H.264 還是 H.265?

但是,如果出現題目中的情況,沒有對碼流進行封裝,而是直接傳輸碼流時,這時候 NALU 中有什麼欄位能標識自己的編碼格式嗎?答案是,沒有這樣明確的欄位能標識碼流的編碼格式。

但是這個問題也不是不能解決,因為 H.264、H.265 碼流本身也是遵循一定格式規範的,我們可以按照它的格式規範進行探測,如果能解析出來正確的資訊,那也可以確定它的編碼格式。

比如,拿 H.265 來說,FFmpeg 中 hevcdec.c 就有對其碼流資料進行探測的函式:

static int hevc_probe(AVProbeData *p)
{
uint32_t code = -1;
int vps = 0, sps = 0, pps = 0, irap = 0;
int i;

for (i = 0; i < p->buf_size - 1; i++) {
code = (code << 8) + p->buf[i];
if ((code & 0xffffff00) == 0x100) {
uint8_t nal2 = p->buf[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 HEVC_NAL_VPS: vps++; break;
case HEVC_NAL_SPS: sps++; break;
case HEVC_NAL_PPS: pps++; break;
case HEVC_NAL_BLA_N_LP:
case HEVC_NAL_BLA_W_LP:
case HEVC_NAL_BLA_W_RADL:
case HEVC_NAL_CRA_NUT:
case HEVC_NAL_IDR_N_LP:
case HEVC_NAL_IDR_W_RADL: irap++; break;
}
}
}

if (vps && sps && pps && irap)
return AVPROBE_SCORE_EXTENSION + 1; // 1 more than .mpg
return 0;
}

所以,我們可以按照編碼格式規範探測,比如 H.265 如果解析出了 pps、sps、vps 的各欄位資訊符合規範,就認為它是 H.265 的編碼;如果不是,在你們的碼流格式範圍中就只剩 H.264 了;接下來將碼流資料交給對應的解碼器解碼即可。

後面是付費技術社群的介紹,你可以跳過不看,也可以瞭解一下。

如果你也對音視訊技術感興趣,比如,符合下面的情況:

  • 在校大學生 → 學習音視訊開發

  • iOS/Android 客戶端開發 → 轉入音視訊領域

  • 直播/短視訊業務開發 → 深入音視訊底層 SDK 開發

  • 音視訊 SDK 開發 → 提升技能,解決優化瓶頸

可以長按識別或掃描下面二維碼,瞭解一下這個社群,根據自己的情況按需加入:

識別二維碼加入我們