H264碼流分析導(dǎo)讀

導(dǎo)讀

H.264碼流結(jié)構(gòu)解析

H.264編碼格式

H.264的功能分為兩層:視頻編碼層(VCL, Video Coding Layer)和網(wǎng)絡(luò)提取層(NAL, Network Abstraction Layer)
VCL數(shù)據(jù)即編碼處理的輸出,它表示被壓縮編碼后的視頻數(shù)據(jù)序列。在VCL數(shù)據(jù)傳輸或存儲(chǔ)之前,這些編碼的VCL數(shù)據(jù),先被映射或封裝進(jìn)NAL單元中。每個(gè)NAL單元包括一個(gè)原始字節(jié)序列負(fù)荷(RBSP, Raw Byte Sequence Payload)、一組對(duì)應(yīng)于視頻編碼的NAL頭信息。RBSP的基本結(jié)構(gòu)是:在原始編碼數(shù)據(jù)的后面填加了結(jié)尾比特。一個(gè)bit“1”若干比特“0”,以便字節(jié)對(duì)齊。

image.png

H.264傳輸

H.264的編碼視頻序列包括一系列的NAL單元,每個(gè)NAL單元包含一個(gè)RBSP,見(jiàn)表1。編碼片(包括數(shù)據(jù)分割片IDR片)和序列RBSP結(jié)束符被定義為VCL NAL單元,其余為NAL單元。典型的RBSP單元序列如圖2所示。每個(gè)單元都按獨(dú)立的NAL單元傳送。單元的信息頭(一個(gè)字節(jié))定義了RBSP單元的類(lèi)型,NAL單元的其余部分為RBSP數(shù)據(jù)。


image.png

image.png
  1. H.264碼流結(jié)構(gòu)圖


    image.png

起始碼:如果NALU對(duì)應(yīng)的Slice為一幀的開(kāi)始,則用4字節(jié)表示,即0x00000001;否則用3字節(jié)表示,0x000001。
NAL Header:forbidden_bit,nal_reference_bit(優(yōu)先級(jí)),nal_unit_type(類(lèi)型)。
脫殼操作:為了使NALU主體不包括起始碼,在編碼時(shí)每遇到兩個(gè)字節(jié)(連續(xù))的0,就插入一字節(jié)0x03,以和起始碼相區(qū)別。解碼時(shí),則將相應(yīng)的0x03刪除掉。

image.png
  1. H.264解碼
    NAL頭信息的nal_referrence_idc(NRI)用于在重建過(guò)程中標(biāo)記一個(gè)NAL單元的重要性,值為0表示這個(gè)NAL單元沒(méi)有用預(yù)測(cè),因此可以被解碼器拋棄而不會(huì)有錯(cuò)誤擴(kuò)散;值高于0表示NAL單元要用于無(wú)漂移重構(gòu),且值越高,對(duì)此NAL單元丟失的影響越大。
    NAL頭信息的隱藏比特位,在H.264編碼器中默認(rèn)為0,當(dāng)網(wǎng)絡(luò)識(shí)別到單元中存在比特錯(cuò)誤時(shí),可將其置為1。隱藏比特位主要用于適應(yīng)不同種類(lèi)的網(wǎng)絡(luò)環(huán)境(比如有線(xiàn)無(wú)線(xiàn)相結(jié)合的環(huán)境)。


    image.png

NAL單元解碼的流程為:首先從NAL單元中提取出RBSP語(yǔ)法結(jié)構(gòu),然后按照如圖4所示的流程處理RBSP語(yǔ)法結(jié)構(gòu)。輸入的是NAL單元,輸出結(jié)果是經(jīng)過(guò)解碼的當(dāng)前圖像的樣值點(diǎn)。
NAL單元中分別包含了序列參數(shù)集和圖像參數(shù)集。圖像參數(shù)集和序列參數(shù)集在其他NAL單元傳輸過(guò)程中作為參考使用,在這些數(shù)據(jù)NAL單元的片頭中,通過(guò)語(yǔ)法元素pic_parameter_set_id設(shè)置它們所使用的圖像參數(shù)集編號(hào);而相應(yīng)的每個(gè)圖像參數(shù)集中,通過(guò)語(yǔ)法元素seq_paramter_set_id設(shè)置他們使用的序列參數(shù)集編號(hào)。

示例分析

結(jié)合laifeng_Android中的AnnexbHelper來(lái)簡(jiǎn)單的看看,如果進(jìn)行解析。
Android硬編碼得到的H264是Annexb這種格式的。

  • 如何獲取NAUL單元
    其實(shí)就是找開(kāi)頭為 0x0001或者0x000001的字節(jié)段
  /**
     * 從硬編出來(lái)的byteBuffer中查找nal
     * @param as
     * @param bb
     * @param bi
     */
    private void avcStartWithAnnexb(AnnexbSearch as, ByteBuffer bb, MediaCodec.BufferInfo bi) {
        as.match = false;
        as.startCode = 0;
        int pos = bb.position();
        while (pos < bi.offset + bi.size - 3) {
            // not match.
            if (bb.get(pos) != 0x00 || bb.get(pos + 1) != 0x00) {
                break;
            }

            // match N[00] 00 00 01, where N>=0
            if (bb.get(pos + 2) == 0x01) {
                as.match = true;
                as.startCode = pos + 3 - bb.position();
                break;
            }
            pos++;
        }
    }
  • 根據(jù)NAL Header內(nèi)的nal_unit_type判斷當(dāng)前幀的類(lèi)型
    根據(jù)上面的類(lèi)型分析,我們知道NAUL里面前8位中的后5位,表示這個(gè)NAUL的類(lèi)型。
    根據(jù)這些可以判斷類(lèi)型。
    而剩下的就是NAUL內(nèi)的數(shù)據(jù)了。
private boolean isSps(byte[] frame) {
        if (frame.length < 1) {
            return false;
        }
        // 5bits, 7.3.1 NAL unit syntax,
        // H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
        //  7: SPS, 8: PPS, 5: I Frame, 1: P Frame
        int nal_unit_type = (frame[0] & 0x1f);
        return nal_unit_type == SPS;
    }

    private boolean isPps(byte[] frame) {
        if (frame.length < 1) {
            return false;
        }
        // 5bits, 7.3.1 NAL unit syntax,
        // H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
        //  7: SPS, 8: PPS, 5: I Frame, 1: P Frame
        int nal_unit_type = (frame[0] & 0x1f);
        return nal_unit_type == PPS;
    }

    private boolean isKeyFrame(byte[] frame) {
        if (frame.length < 1) {
            return false;
        }
        // 5bits, 7.3.1 NAL unit syntax,
        // H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
        //  7: SPS, 8: PPS, 5: I Frame, 1: P Frame
        int nal_unit_type = (frame[0] & 0x1f);
        return nal_unit_type == IDR;
    }

    private static boolean isAccessUnitDelimiter(byte[] frame) {
        if (frame.length < 1) {
            return false;
        }
        // 5bits, 7.3.1 NAL unit syntax,
        // H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
        //  7: SPS, 8: PPS, 5: I Frame, 1: P Frame
        int nal_unit_type = (frame[0] & 0x1f);
        return nal_unit_type == AccessUnitDelimiter;
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容