【h.264】H264码流SPS解析

Date: 2018.9.10


#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <cstring>
#include <iostream>
#include <string.h>
#include "D264.h"
using namespace std;
int main(int argc, const char *argv[])
{
    FILE *BitStream=NULL;
    unsigned char *SPS_nalu;
    unsigned char sps_profole_idc = 1;
    int sps_width = 1;
    int sps_height = 1;
    size_t len = 24;

    BitStream = fopen(argv[1], "rb");
    SPS_nalu = (unsigned char*)malloc(len + 256);
    fread(SPS_nalu, 1,len, BitStream);
    //memcpy(SPS_nalu, BitStream, len);

    if (argc < 2 || !BitStream)
    {
        cout << "error, please check the input!!!!!!!!!!!!!!!!!!!" << endl;
    }

    if (1/*((BitStream[4])&0x1f) == 0x7*/)  //sps
    {
        cout << "AVC_sps_analysis :" << endl;
        int videoW = -1;
        int videoH = -1;
        unsigned char profile_idc = -1;
        cout << "videoH = " << videoH << endl;
        cout << "videoW = " << videoW << endl;
        cout << "profile_idc = " << profile_idc << endl;

        D264_StartSlice(SPS_nalu, len, &videoW, &videoH, &profile_idc);

        sps_profole_idc = profile_idc;
        sps_width = videoW;
        sps_height = videoH;
    }


    cout << "sps_profile_idc = " << sps_profole_idc << endl;
    cout << "sps_width = " << sps_width << endl;
    cout << "sps_height = " << sps_height << endl;
    free(SPS_nalu);
    SPS_nalu = NULL;
    fclose(BitStream);


    return 0;
}

int D264_BitstreamGetBs(BITSTREAM *bs,unsigned char *nalu_buf, signed int buf_len, NALU *nalu)
{
    signed int start_code_len;
    signed int nalu_len;
    printf("%d %d %d %d 
", nalu_buf[0], nalu_buf[1], nalu_buf[2], nalu_buf[3] );
    if(nalu_buf[0] == 0 && nalu_buf[1] == 0 && nalu_buf[2] == 0 && nalu_buf[3] == 1)
    {
        start_code_len = 4;
    }
    else if(nalu_buf[0] == 0 && nalu_buf[1] == 0 && nalu_buf[2] == 1)
    {
        start_code_len = 3;
    }
    else
    {
        start_code_len = 0;
    }
   // printf("start_code_len=%d
", start_code_len);

    nalu->nal_reference_idc    = (nalu_buf[start_code_len]>>5) & 3;
    nalu->nal_unit_type        = (nalu_buf[start_code_len]) & 0x1f;


        nalu_len = D264_EBSP_to_RBSP(nalu_buf, (unsigned char *)bs->pStart, buf_len, 1 + start_code_len);


        bs->pStart = nalu_buf+1+start_code_len;
    }

    bs->nBsLength   = D264_RBSP_to_SODB((unsigned char *)bs->pStart, nalu_len);

    D264_DecBitstreamInit(bs,(unsigned char *)bs->pStart);

    return ERR_OK;
}

int D264_StartSlice(uint8_t *nalu_buf,int32_t buf_len,int *pWidth,int *pHeight, uint8_t *pProfile_idc)
{
    int ret;
    BITSTREAM   bs[1];//     = &pEnc->m_bs;
    NALU nalu;
    int CurHdr;
    unsigned char *pAlignBs = pBs+((BS_ALIGN_BYTE-((long)pBs)%8)&(BS_ALIGN_BYTE-1));

    int bslen = buf_len > 256 ? 256 : buf_len;
    memcpy(pAlignBs,nalu_buf,bslen);

    if(bslen <= 0)
        return ERR_FAIL;
    ret = D264_BitstreamGetBs(bs, pAlignBs, bslen, &nalu);
    if(ret != ERR_OK)
        return ERR_FAIL;
    CurHdr = D264_DecSliceHdr(bs, &nalu,pWidth,pHeight,pProfile_idc);
    if(CurHdr != PARAM_ERR && CurHdr != NOT_SUPPORTED && CurHdr != ERR_FAIL)
    {
        if(CurHdr == END_XPS)
            return ERR_OK;
    }
    else
    {
        return ERR_FAIL;
    }

    return ERR_OK;
}

int D264_RBSP_to_SODB(unsigned char *pStreamStart, int last_byte_pos)
{
    int ctr_bit, bitoffset = 0;
    //find trailing 1 bits
    ctr_bit = (pStreamStart[last_byte_pos-1] & (0x01 << bitoffset));
    while (ctr_bit == 0)
    {
        bitoffset++;
        if(bitoffset == 8)
        {
            last_byte_pos -= 1;
            bitoffset = 0;
        }
        ctr_bit = pStreamStart[last_byte_pos - 1] & (0x01 << (bitoffset));
    }
    return(last_byte_pos);
}


int D264_EBSP_to_RBSP(unsigned char *nalu_buf, unsigned char *bs_buffer, int end_bytepos, int begin_bytepos)
{
    int i, j, count = 0;
    int tmp;

    int bFind03 = 0;
    int trid;

    if(end_bytepos < begin_bytepos)
    {
        return end_bytepos;
    }
    for(j = 0, i = begin_bytepos; i < end_bytepos; i++)
    {
        tmp = nalu_buf[i];
        count = (tmp  != 0x03 || count != ZEROBYTES_SHORTSTARTCODE) ? bs_buffer[j++] = tmp ,(!tmp ) * (count+1) : 0;
    }

    return j;
}
#endif

int D264_find_start_code (unsigned char *buf, int zeros_in_startcode)
{
    int i;
    int info;
    info = 1;
    for (i = 0; i < zeros_in_startcode; i++)
    {
        if(buf[i] != 0)
        {
            info = 0;
        }
    }
    if(buf[i] != 1)
    {
        info = 0;
    }
    return info;
}


int D264_more_rbsp_data (unsigned char buffer[],int totbitoffset,int bytecount)
{
    int ctr_bit, byteoffset, bitoffset;
    // there is more until we're in the last byte
    byteoffset = totbitoffset >> 3;
    if (byteoffset < (bytecount-1))
    {
        return TRUE;
    }
    else if (byteoffset >= (bytecount))
    {
        return FALSE;
    }
    else
    {
        // read one bit
        bitoffset  = 7 - (totbitoffset & 7);
        ctr_bit = (buffer[byteoffset] & (0x01 << bitoffset));
        // a stop bit has to be one
        if (ctr_bit == 0)
        {
            return TRUE;
        }
        else
        {
            bitoffset--;
            while (bitoffset >= 0)
            {
                ctr_bit = (buffer[byteoffset] & (0x01 << bitoffset));   // set up control bit
                if (ctr_bit > 0)
                {
                    return TRUE;
                }
                bitoffset--;
            }
            return FALSE;
        }
    }
}

SPS解析函数:


signed int  D264_interpret_SPS (BITSTREAM *bs, SEQ_PARAMETER_SET *sps,int *pWidth,int *pHeight)
{

    signed int i;
    signed int reserved_zero;
    int tmp;

    if(bs->pStart == NULL)
        return 1;
    if(sps == NULL)
        return 1;

    sps->profile_idc                               = D264_BitstreamGetBitsNotInline  (bs,8);

    sps->constrained_set0_flag                     = D264_BitstreamGetBitsNotInline(bs,1);
    sps->constrained_set1_flag                     = D264_BitstreamGetBitsNotInline(bs,1);
    sps->constrained_set2_flag                     = D264_BitstreamGetBitsNotInline(bs,1);
    reserved_zero                                  = D264_BitstreamGetBitsNotInline(bs,5);
//  assert (reserved_zero == 0);
    if(reserved_zero != 0)
        return 1;
    sps->level_idc                                 = D264_BitstreamGetBitsNotInline(bs,8);
//  if(sps->level_idc != 30)
//  {
//      printf("sorry! only level 2.0 is supported!
");
//      return 1;
//  }

    sps->seq_parameter_set_id                      = D264_ue_v (bs);


    if((sps->profile_idc==FREXT_HP   ) ||
        (sps->profile_idc==FREXT_Hi10P) ||
        (sps->profile_idc==FREXT_Hi422) ||
        (sps->profile_idc==FREXT_Hi444))
    {
        sps->chroma_format_idc                      = D264_ue_v (bs);

        // Residue Color Transform
        if(sps->chroma_format_idc == 3)
            sps->residue_transform_flag = D264_BitstreamGetBitsNotInline(bs,1);

        sps->bit_depth_luma_minus8                  = D264_ue_v (bs);
        sps->bit_depth_chroma_minus8                = D264_ue_v (bs);
        sps->lossless_qpprime_flag                  = D264_BitstreamGetBitsNotInline(bs,1);

        sps->seq_scaling_matrix_present_flag        = D264_BitstreamGetBitsNotInline(bs,1);

        if(sps->seq_scaling_matrix_present_flag)
        {
            for(i=0; i<8; i++)
            {
                sps->seq_scaling_list_present_flag[i]   = D264_BitstreamGetBitsNotInline(bs,1);
                if(sps->seq_scaling_list_present_flag[i])
                {
                    if(i<6)
                        Scaling_List(sps->ScalingList4x4[i], 16, &sps->UseDefaultScalingMatrix4x4Flag[i], bs);
                    else
                        Scaling_List(sps->ScalingList8x8[i-6], 64, &sps->UseDefaultScalingMatrix8x8Flag[i-6], bs);
                }
            }
        }
  }



    sps->log2_max_frame_num_minus4                 = D264_ue_v (bs);
    sps->pic_order_cnt_type                        = D264_ue_v (bs);
    if (sps->pic_order_cnt_type == 0)
    {
        sps->log2_max_pic_order_cnt_lsb_minus4     = D264_ue_v (bs);
    }
    else if (sps->pic_order_cnt_type == 1)
    {
        sps->delta_pic_order_always_zero_flag      = D264_BitstreamGetBitsNotInline  (bs,1);
        sps->offset_for_non_ref_pic                = D264_se_v (bs);
        sps->offset_for_top_to_bottom_field        = D264_se_v (bs);
        sps->num_ref_frames_in_pic_order_cnt_cycle = D264_ue_v (bs);

        for(i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++)
        {
            sps->offset_for_ref_frame[i]           = D264_se_v (bs);
        }
    }

    tmp  = D264_ue_v (bs);
    if(sps->num_ref_frames!= tmp)
        sps->param_changed_flag = 1;
    sps->num_ref_frames = tmp;

    sps->gaps_in_frame_num_value_allowed_flag      = D264_BitstreamGetBitsNotInline  (bs,1);

    tmp                   = D264_ue_v (bs);
    if(sps->pic_width_in_mbs_minus1!= tmp)
        sps->param_changed_flag = 1;
    sps->pic_width_in_mbs_minus1 = tmp;

    tmp                   = D264_ue_v (bs);
    if(sps->pic_height_in_map_units_minus1!= tmp)
        sps->param_changed_flag = 1;
    sps->pic_height_in_map_units_minus1 = tmp;

    *pWidth = sps->pic_width_in_mbs_minus1*16+16;
    *pHeight = sps->pic_height_in_map_units_minus1*16+16;



    if(*pHeight == 1088)
        *pHeight = 1080;


    sps->frame_mbs_only_flag                       = D264_BitstreamGetBitsNotInline  (bs,1);
    if (!sps->frame_mbs_only_flag)
    {
        sps->mb_adaptive_frame_field_flag          = D264_BitstreamGetBitsNotInline  (bs,1);
    }
    sps->direct_8x8_inference_flag                 = D264_BitstreamGetBitsNotInline  (bs,1);
    sps->frame_cropping_flag                       = D264_BitstreamGetBitsNotInline  (bs,1);

    if (sps->frame_cropping_flag)
    {
        sps->frame_cropping_rect_left_offset       = D264_ue_v (bs);
        sps->frame_cropping_rect_right_offset      = D264_ue_v (bs);
        sps->frame_cropping_rect_top_offset        = D264_ue_v (bs);
        sps->frame_cropping_rect_bottom_offset     = D264_ue_v (bs);
    }
    sps->vui_parameters_present_flag               = D264_BitstreamGetBitsNotInline  (bs,1);
#ifdef _PRINT_DEBUG_INFO
    if (sps->vui_parameters_present_flag)
    {
        printf ("VUI sequence parameters present but not supported, ignored
");
    }
#endif

    sps->Valid  = TRUE;
    return 0;
}
/**/


signed int  D264_process_SPS (BITSTREAM *bs,SEQ_PARAMETER_SET *tmp_sps,int *pWidth,int *pHeight)
{
    if ( D264_interpret_SPS(bs, tmp_sps,pWidth,pHeight) != 0 )
    {
        return 1;
    }
    return 0;
}


signed int  D264_DecSliceHdr(BITSTREAM *bs, NALU *nalu,int *pWidth,int *pHeight, unsigned char *pProfile_idc)
{
    signed int old_max_dpb;
    signed int          re_status;
    signed int          current_header = 0;
    signed int          param_changed_flag = 0;
    signed int          old_width_in_mb;
    signed int          old_height_in_mb;
    SEQ_PARAMETER_SET m_sps[1];

    if(nalu->nal_unit_type == NALU_TYPE_SPS)
    {
        re_status = D264_process_SPS(bs, m_sps,pWidth,pHeight);
        if ( 0 != re_status )
        {
            return PARAM_ERR;
        }
        else
        {
            *pProfile_idc = m_sps[0].profile_idc;     
            return END_XPS;
        }
    }
    else
    {
        return PARAM_ERR;
    }
}

码流VLC解析:

#include <cstring>
#include "../inc/E264_vlc.h"

unsigned int bitc(unsigned short src)
{
    int i;
    int nBit = 0;
    for(i=0;i<8;i++)
    {
        nBit += (((1<<i)&src) != 0);
    }
    return nBit;
}
unsigned int  _bitc4(unsigned int src)
{
    int result;

    int i;
    for(i=0;i<4;i++)
    {
        ((unsigned char *)(&result))[i] = bitc(((unsigned char *)(&src))[i]);
    }
    return result;
}
unsigned int _swap4(unsigned int src)
{
    int result = 0;
    int i;

    result = 0;

    ((unsigned char *)(&result))[0] =  ((unsigned char *)(&src))[1];
    ((unsigned char *)(&result))[1] =  ((unsigned char *)(&src))[0];
    ((unsigned char *)(&result))[2] =  ((unsigned char *)(&src))[3];
    ((unsigned char *)(&result))[3] =  ((unsigned char *)(&src))[2];

    return result;

}
unsigned int _packlh2   (unsigned int src1, unsigned int src2)
{
    unsigned int result;
    ((unsigned short *)(&result))[0] =  ((unsigned short *)(&src2))[1];

    ((unsigned short *)(&result))[1] =  ((unsigned short *)(&src1))[0];
    return result;
}

_INLINE_ void D264_GetNal(BITSTREAM *bs,unsigned int iPrevData,unsigned int iData)
{
    unsigned char* naluBuffer = bs->pCurrent-4;
    int nBsLength = 0;
    int i;
    int count;
    unsigned char *pStart = (unsigned char *)(&iData);
    unsigned char data;

    count = (!(iPrevData&0x000000ff)+!(iPrevData&0x0000ffff));
    //  count = (iPrevData&0xff000000) ? 0:count;

    for(i=0; i < 4; i++)
    {
        data = naluBuffer[nBsLength++];
        (count == ZEROBYTES_SHORTSTARTCODE && (data == 0x03)) ? nBsLength++ : 0;
        count = count == ZEROBYTES_SHORTSTARTCODE ? 0:count;
        pStart[i] = naluBuffer[nBsLength-1];
        count = data == 0 ? count+1:0;
    }
    iData = _packlh2(iData,iData);
    iData = _swap4(iData);

    bs->DataB = iData;


    bs->pCurrent+=nBsLength-4;
}
#endif

int _cmpgtu4(int src1,int src2)
{
    int result;
    int i;

    result = 0;
    for(i=0;i<4;i++)
    {
        result |=  (((unsigned char *)(&src1))[i]>((unsigned char *)(&src2))[i])<<i;
    }
    return result;
}
int _norm(unsigned int val)
{
    int size = 0;
    while(val)
    {
        val>>=1;
        size++;
    }

    return 31-size;
}

#pragma CODE_SECTION(BitstreamShowBits,".H264Dec_L2_Code_GetMBData")
unsigned int  BitstreamShowBits(BITSTREAM * const bs,
                                            const unsigned int bits)
{
    int iPos = bs->iPos;
    unsigned int DataA = bs->DataA;
    unsigned int DataB = bs->DataB;
    int rs = 32 - bits;
    int nbit = (bits + iPos) - 32;
    unsigned int l;


    l = nbit <= 0?(DataA << iPos) >> rs
        :((DataA << iPos) >> rs) | (DataB >> (32 - nbit));

    return l;
}

#pragma CODE_SECTION(D264_BitstreamGetBits,".H264Dec_L2_Code_GetMBData")//Get(0)
static _INLINE_ unsigned int  D264_BitstreamGetBits(BITSTREAM * const bs,
                                                const unsigned int bits)
{
    int iPos = bs->iPos;
    unsigned int DataA = bs->DataA;
    unsigned int DataB = bs->DataB;
    int nbit = (bits + iPos) - 32;
#if 1
    unsigned int l = nbit <= 0?(DataA << iPos) >> (32 - bits)
        :((DataA << iPos)>>(32-bits)) | (DataB >> (32 - nbit));
#else
    unsigned int l = nbit <= 0?(unsigned __int64)(DataA << iPos) >> (32 - bits)
        :((unsigned __int64)(DataA << iPos)>>(32-bits)) | (unsigned __int64)(DataB >> (32 - nbit));

#endif
    iPos += bits;
    if (iPos >= 32)
    {
        unsigned int DataA = bs->DataA;
        unsigned int DataB = bs->DataB;
        int data;// = *(int*)(bs->pCurrent);
        memcpy(&data, bs->pCurrent, sizeof(int));
        iPos -= 32;
        DataA = DataB;

        data = _packlh2(data,data);
        DataB = _swap4(data);

        bs->pCurrent+=sizeof(int);
        bs->DataA = DataA;
        bs->DataB = DataB;

#ifdef E264_NAL_NEW_003
        {
            int c0,c1;

            c0=_cmpgtu4(0x00000101,DataA);
            c1=_cmpgtu4(0x01010100,DataB);

            if(_bitc4(c0)+_bitc4(c1)>=2)
            {
                D264_GetNal(bs,DataA,DataB);
            }
        }
#endif
    }
    bs->iPos = iPos;
    return l;
}

#pragma CODE_SECTION(D264_BitstreamGetBitsNotInline,".H264Dec_L2_Code")
unsigned int  D264_BitstreamGetBitsNotInline(BITSTREAM * const bs,
                                         const unsigned int bits)
{

    return D264_BitstreamGetBits(bs,bits);
}

#pragma CODE_SECTION(D264_linfo_ue,".H264Dec_L2_Code_GetMBData")
_INLINE_ signed int D264_linfo_ue(signed int len, signed int info)
{
    return ((1 << (len >> 1)) + info - 1);
}
#pragma CODE_SECTION(D264_linfo_se,".H264Dec_L2_Code_GetMBData")
_INLINE_ signed int D264_linfo_se(signed int len,  signed int info)
{
    signed int n;
    signed int value;
    n = (1 << (len >> 1)) + info - 1;
    value = (n + 1) >> 1;
    return ( (n & 0x01) == 0 ? -value : value);// lsb is signed bit
}

#pragma CODE_SECTION(D264_get_VLC_symbol,".H264Dec_L2_Code_GetMBData")
signed int D264_get_VLC_symbol (BITSTREAM *bs, signed int *info)
{
    signed int ctr_bit;
    unsigned int tmp;
    int len = 0;
    int a;

    //  int lennew = 0;
    int code = BitstreamShowBits(bs,16);

    len = _norm(code) + 1 - (32-16);

#if 0
    BitstreamSkip(bs,len+1);


    *info = D264_BitstreamGetBitsLenZero(bs,len);
#else
    *info = D264_BitstreamGetBits(bs,len*2+1) & ((1<<len)-1);

#endif

    return ((len<<1) + 1);

}

#pragma CODE_SECTION(D264_ue_v,".H264Dec_L2_Code")
signed int D264_ue_v (BITSTREAM *bs)
{
    signed int info;
    signed int sym_len;
    signed int val;

    sym_len =  D264_get_VLC_symbol (bs, &info);

    val = D264_linfo_ue(sym_len, info);

    return val;
}

#pragma CODE_SECTION(D264_se_v,".H264Dec_L2_Code")
signed int D264_se_v (BITSTREAM *bs)
{
    signed int info;
    signed int sym_len;
    signed int val;

    sym_len =  D264_get_VLC_symbol (bs, &info);
    val = D264_linfo_se(sym_len, info);
    return val;
}


THE END!

原文地址:https://www.cnblogs.com/SoaringLee/p/10532373.html