zoukankan      html  css  js  c++  java
  • 【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!

  • 相关阅读:
    oracle无法使用sysdba的解决办法
    打开计算机管理的命令
    python 多进程详解(Multiprocessing模块)
    zabbix使用Percona数据库tokudb引擎
    python自定义异常类
    xml(打补丁)设置timestamp类型指定的默认值以及varchar2类型的默认值
    This inspection suggests to replace null check with Object/Stream static method
    后端Itext生成pdf到传到前端,支票打印A4纸
    easyexcel导入获取表头并且表头为不固定列
    9. 云停车(芊熠相机)
  • 原文地址:https://www.cnblogs.com/SoaringLee/p/10532373.html
Copyright © 2011-2022 走看看