zoukankan      html  css  js  c++  java
  • h265文件分析(纯c解析代码)

    参考链接: 1. HEVC码流解析 https://blog.csdn.net/CrystalShaw/article/details/80624804
          2. HEVC编码结构:序列参数集SPS、图像参数集PPS、视频参数集VPS https://blog.csdn.net/lin453701006/article/details/52797104
          3. H265码流结构分析 https://blog.csdn.net/u011003120/article/details/83411445#11_H265_4

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <arpa/inet.h>
      5 
      6 #define TAB44 "    "
      7 #define PRINTF_DEBUG
      8 
      9 #define PRTNTF_STR_LEN 10
     10 
     11 typedef enum e_hevc_nalu_type {
     12     HEVC_NAL_TRAIL_N    = 0,
     13     HEVC_NAL_TRAIL_R    = 1,
     14     HEVC_NAL_TSA_N      = 2,
     15     HEVC_NAL_TSA_R      = 3,
     16     HEVC_NAL_STSA_N     = 4,
     17     HEVC_NAL_STSA_R     = 5,
     18     HEVC_NAL_RADL_N     = 6,
     19     HEVC_NAL_RADL_R     = 7,
     20     HEVC_NAL_RASL_N     = 8,
     21     HEVC_NAL_RASL_R     = 9,
     22     HEVC_NAL_VCL_N10    = 10,
     23     HEVC_NAL_VCL_R11    = 11,
     24     HEVC_NAL_VCL_N12    = 12,
     25     HEVC_NAL_VCL_R13    = 13,
     26     HEVC_NAL_VCL_N14    = 14,
     27     HEVC_NAL_VCL_R15    = 15,
     28     HEVC_NAL_BLA_W_LP   = 16,
     29     HEVC_NAL_BLA_W_RADL = 17,
     30     HEVC_NAL_BLA_N_LP   = 18,
     31     HEVC_NAL_IDR_W_RADL = 19,
     32     HEVC_NAL_IDR_N_LP   = 20,
     33     HEVC_NAL_CRA_NUT    = 21,
     34     HEVC_NAL_IRAP_VCL22 = 22,
     35     HEVC_NAL_IRAP_VCL23 = 23,
     36     HEVC_NAL_RSV_VCL24  = 24,
     37     HEVC_NAL_RSV_VCL25  = 25,
     38     HEVC_NAL_RSV_VCL26  = 26,
     39     HEVC_NAL_RSV_VCL27  = 27,
     40     HEVC_NAL_RSV_VCL28  = 28,
     41     HEVC_NAL_RSV_VCL29  = 29,
     42     HEVC_NAL_RSV_VCL30  = 30,
     43     HEVC_NAL_RSV_VCL31  = 31,
     44     HEVC_NAL_VPS        = 32,
     45     HEVC_NAL_SPS        = 33,
     46     HEVC_NAL_PPS        = 34,
     47     HEVC_NAL_AUD        = 35,
     48     HEVC_NAL_EOS_NUT    = 36,
     49     HEVC_NAL_EOB_NUT    = 37,
     50     HEVC_NAL_FD_NUT     = 38,
     51     HEVC_NAL_SEI_PREFIX = 39,
     52     HEVC_NAL_SEI_SUFFIX = 40
     53 } E_HEVC_NALU_TYPE;
     54 
     55 /********************************************************************************
     56 typedef struct t_h264_nalu_header
     57 {
     58     unsigned char forbidden_bit:1, nal_reference_idc:2, nal_unit_type:5;
     59 } T_H264_NALU_HEADER; (1个字节, hevc header为2个字节)
     60 *********************************************************************************/
     61 typedef struct t_h265_nalu_header
     62 {
     63     unsigned short forbidden_zero_bit:1, nal_unit_type:6, nuh_layer_id:6, nuh_temporal_id_plus1:3;
     64 } T_H265_NALU_HEADER;
     65 
     66 typedef struct t_h265_nalu
     67 {
     68     int startCodeLen;
     69     
     70     T_H265_NALU_HEADER h265NaluHeader;
     71     
     72     unsigned int bodyLen;
     73     
     74     unsigned char *bodyData;
     75 } T_H265_NALU;
     76 
     77 /**********************************************************************************
     78  1. h265的起始码: 0x000001(3 Bytes)或0x00000001(4 Bytes);
     79  2. 文件流中用起始码来区分NALU;
     80  3. 如果NALU类型为vps, sps, pps, 或者解码顺序为第一个AU的第一个NALU, 起始码前面再加一个0x00
     81     视频流的首个NALU的起始码前加入0x00(4 Bytes的由来).
     82 ***********************************************************************************/
     83 static int FindStartCode3Bytes(unsigned char *scData)
     84 {
     85     int isFind = 0;
     86 
     87     if ((0==scData[0]) && (0==scData[1]) && (1==scData[2]))
     88     {
     89         isFind = 1;
     90     }
     91     
     92     return isFind;
     93 }
     94 
     95 static int FindStartCode4Bytes(unsigned char *scData)
     96 {
     97     int isFind = 0;
     98 
     99     if ((0==scData[0]) && (0==scData[1]) && (0==scData[2]) && (1 == scData[3]))
    100     {
    101         isFind = 1;
    102     }
    103     
    104     return isFind;
    105 }
    106 
    107 static int GetNaluDataLen(int startPos, int h265BitsSize, unsigned char *h265Bits)
    108 {
    109     int parsePos = 0;
    110     
    111     parsePos = startPos;
    112     
    113     while (parsePos < h265BitsSize)
    114     {
    115         if (FindStartCode3Bytes(&h265Bits[parsePos]))
    116         {
    117             return parsePos - startPos;
    118         }
    119         else if (FindStartCode4Bytes(&h265Bits[parsePos]))
    120         {
    121             return parsePos - startPos;
    122         }
    123         else
    124         {
    125             parsePos++;
    126         }
    127     }
    128     
    129     return parsePos - startPos; // if file is end
    130 }
    131 
    132 static void ParseNaluData(const unsigned int naluLen, unsigned char* const nuluData)
    133 {
    134     static int naluNum = 0;
    135     
    136     unsigned char *data = NULL;
    137     unsigned char typeStr[PRTNTF_STR_LEN+1] = {0};
    138     
    139     T_H265_NALU_HEADER h265NaluHeader = {0};
    140     
    141     data = nuluData;
    142     
    143     memset(&h265NaluHeader, 0x0, sizeof(T_H265_NALU_HEADER));
    144     
    145     h265NaluHeader.nal_unit_type = ((data[0]>>1) & 0x3f);
    146 
    147     naluNum++;
    148     
    149 #ifdef PRINTF_DEBUG
    150     switch (h265NaluHeader.nal_unit_type)
    151     {
    152         case HEVC_NAL_TRAIL_N:
    153             sprintf(typeStr, "B SLICE");
    154             break;
    155             
    156         case HEVC_NAL_TRAIL_R:
    157             sprintf(typeStr, "P SLICE");
    158             break;
    159         
    160         case HEVC_NAL_IDR_W_RADL:
    161             sprintf(typeStr, "IDR");
    162             break;
    163             
    164         case HEVC_NAL_VPS:
    165             sprintf(typeStr, "VPS");
    166             break;
    167         
    168         case HEVC_NAL_SPS:
    169             sprintf(typeStr, "SPS");
    170             break;
    171         
    172         case HEVC_NAL_PPS:
    173             sprintf(typeStr, "PPS");
    174             break;
    175             
    176         case HEVC_NAL_SEI_PREFIX:
    177             sprintf(typeStr, "SEI");
    178             break;
    179 
    180         default:
    181             sprintf(typeStr, "NTYPE(%d)", h265NaluHeader.nal_unit_type);
    182             break;
    183     }
    184     
    185     printf("%5d| %7s| %8d|
    ", naluNum, typeStr, naluLen);
    186 #endif
    187 }
    188 
    189 int main(int argc, char *argv[])
    190 {
    191     int fileLen = 0;
    192     int naluLen = 0;
    193     int h265BitsPos = 0; /* h265, hevc; h264, avc系列, Advanced Video Coding */
    194 
    195     unsigned char *h265Bits = NULL;
    196     unsigned char *naluData = NULL;
    197     
    198     FILE *fp = NULL;
    199     
    200     if (2 != argc)
    201     {
    202         printf("Usage: flvparse **.flv
    ");
    203 
    204         return -1;
    205     }
    206 
    207     fp = fopen(argv[1], "rb");
    208     if (!fp)
    209     {
    210         printf("open file[%s] error!
    ", argv[1]);
    211 
    212         return -1;
    213     }
    214     
    215     fseek(fp, 0, SEEK_END);
    216     
    217     fileLen = ftell(fp);
    218     
    219     fseek(fp, 0, SEEK_SET);
    220     
    221     h265Bits = (unsigned char*)malloc(fileLen);
    222     if (!h265Bits)
    223     {
    224         printf("maybe file is too long, or memery is not enough!
    ");
    225         
    226         fclose(fp);
    227     
    228         return -1;
    229     }
    230     
    231     memset(h265Bits, 0x0, fileLen);
    232     
    233     if (fread(h265Bits, 1, fileLen, fp) < 0)
    234     {
    235         printf("read file data to h265Bits error!
    ");
    236         
    237         fclose(fp);
    238         free(h265Bits);
    239         
    240         h265Bits = NULL;
    241         
    242         return -1;
    243     }
    244     
    245     fclose(fp);
    246     
    247     printf("-----+--- NALU Table --+
    ");
    248     printf(" NUM |  TYPE |   LEN   |
    ");
    249     printf("-----+-------+---------+
    ");
    250 
    251     while (h265BitsPos < (fileLen-4))
    252     {
    253         if (FindStartCode3Bytes(&h265Bits[h265BitsPos]))
    254         {
    255             naluLen = GetNaluDataLen(h265BitsPos+3, fileLen, h265Bits);
    256 
    257             naluData = (unsigned char*)malloc(naluLen);
    258             if (naluData)
    259             {
    260                 memset(naluData, 0x0, naluLen);
    261                 
    262                 memcpy(naluData, h265Bits+h265BitsPos+3, naluLen);
    263                 
    264                 ParseNaluData(naluLen, naluData);
    265                 
    266                 free(naluData);
    267                 naluData = NULL;
    268             }
    269             
    270             h265BitsPos += (naluLen+3);
    271         }
    272         else if (FindStartCode4Bytes(&h265Bits[h265BitsPos]))
    273         {
    274             naluLen = GetNaluDataLen(h265BitsPos+4, fileLen, h265Bits);
    275 
    276             naluData = (unsigned char*)malloc(naluLen);
    277             if (naluData)
    278             {
    279                 memset(naluData, 0x0, naluLen);
    280 
    281                 memcpy(naluData, h265Bits+h265BitsPos+4, naluLen);
    282 
    283                 ParseNaluData(naluLen, naluData);
    284                 
    285                 free(naluData);
    286                 naluData = NULL;
    287             }
    288             
    289             h265BitsPos += (naluLen+4);
    290         }
    291         else
    292         {
    293             h265BitsPos++;
    294         }
    295     }
    296 
    297     return 0;
    298 }
    View Code

      最后如果您觉得本篇对您有帮助,可以打赏下,谢谢!!!

  • 相关阅读:
    xmlTextTextReaderNodeType来读取XML元素的类型
    [转]关于两个坐标点的距离的计算问题
    Incorrect decrement of the reference count of an object that is not owned at this point by the caller1
    让ipad时时显示内存剩余量
    【转】苹果开发者账号注册流程
    自定义百度地图气泡
    [转] iOS 常用数学函数
    [转]JDK环境变量的配置
    纬度在换算距离上一度等于多少公里?
    [转]UIDevice uniqueGlobalDeviceIdentifier(百度地图API的那些事)
  • 原文地址:https://www.cnblogs.com/leaffei/p/10553783.html
Copyright © 2011-2022 走看看