当前位置:   article > 正文

解析H264的SPS信息_h264 sps解析

h264 sps解析

在做音视频开发的时候,存在不解码视频帧的前提下需要获取视频宽高、帧率等信息,而H.264中的SPS数据可为我们提供这些相关的信息。在此之前,我们需要对一些协议和算法有一定的初步了解,后文中有完整的代码展示。

H.264协议
我们在此不讲解H.264协议,但是我们需要了解NAL单元语法(NAL unit syntax)、序列参数集数据语法(Sequence parameter set data syntax)、视频可用参数语法(VUI parameters syntax)。具体可去ITU-T官网下载H.264文档,我查看的是T-REC-H.264-201704-I!!PDF-E.pdf。

Sequence parameter set data syntax

VUI parameters syntax


第一列:相关参数信息名称;

第二列:规定条带数据可以至多划分为三种条带数据类别(这个可以不用理解);

第三列中的u(n)表示:使用n位无符号整数表示,由n位bit换算得到,即从左到右读取n个bit位所表示的值;ue(v)表示:无符号指数哥伦布编码值;ue(v)表示:有符号指数哥伦布编码值。

u(n)代码实现:

  1. static UINT u(sps_bit_stream *bs, BYTE bitCount)
  2. {
  3.     UINT val = 0;
  4.     for (BYTE i=0; i<bitCount; i++) {
  5.         val <<= 1;
  6.         if (eof(bs)) {
  7.             val = 0;
  8.             break;
  9.         } else if (bs->data[bs->index / 8] & (0x80 >> (bs->index % 8))) {     //计算index所在的位是否为1
  10.             val |= 1;
  11.         }
  12.         bs->index++;
  13.     }
  14.     
  15.     return val;
  16. }


指数哥伦布编码
Golomb编码是一种无损的数据压缩方法,由数学家Solomon W.Golomb在1960年代发明。Golomb编码只能对非负整数进行编码,符号表中的符号出现的概率符合几何分布(Geometric Distribution)时,使用Golomb编码可以取得最优效果,也就是说Golomb编码比较适合小的数字比大的数字出现概率比较高的编码。它使用较短的码长编码较小的数字,较长的码长编码较大的数字。在此,我们只需要了解:无符号指数哥伦布编码ue(v)、有符号指数哥伦布编码se(v)。

无符号指数哥伦布编码(UE)
哥伦布编码的码字code_word由三部分组成:code_word = [M个0] + [1] + [Info]
其中,Info是一个携带信息的M位数据,每个哥伦布码的长度为(2M+1)位,每个码字都可由code_num产生。
根据码字code_word解码出code_num值的过程如下:
1. 首先读入M位以"1"为结尾的0;
2. 根据得到的M,读入接下来的M位Info数据;
3. 根据这个公式得到计算结果code_num = Info – 1 + 2M

代码实现:

  1. static UINT ue(sps_bit_stream *bs)
  2. {
  3.     UINT zeroNum = 0;
  4.     while (u(bs, 1) == 0 && !eof(bs) && zeroNum < 32) {
  5.         zeroNum ++;
  6.     }
  7.     
  8.     return (UINT)((1 << zeroNum) - 1 + u(bs, zeroNum));
  9. }


有符号指数哥伦布编码(SE)
有符号的指数哥伦布编码值是通过无符号的指数哥伦布编码的值通过换算得到的,其换算关系为:n = (-1)^(k+1) * ceil(k/2)。

代码实现:

  1. INT se(sps_bit_stream *bs)
  2. {
  3.     INT ueVal = (INT)ue(bs);
  4.     double k = ueVal;
  5.     
  6.     INT seVal = (INT)ceil(k / 2);     //ceil:返回大于或者等于指定表达式的最小整数
  7.     if (ueVal % 2 == 0) {       //偶数取反,即(-1)^(k+1)
  8.         seVal = -seVal;
  9.     }
  10.     
  11.     return seVal;
  12. }


SPS参数分析
视频宽高(Width、Height)获取
从H.264协议文档中可以看出视频宽高涉及到的参数有:

pic_width_in_mbs_minus1:加1指定以宏块(16*16)为单位的每个解码图像的宽度,即PicWidthInSamplesL = (pic_width_in_mbs_minus1 + 1) * 16 ;

pic_height_in_map_units_minus1:加1指定解码帧或场中的一个切片组的高度,即PicSizeInMapUnits = PicWidthInMbs * (pic_height_in_map_units_minus1 + 1) ;

frame_mbs_only_flag:等于0指明了视频序列的编码图象可能是编码场或编码帧,等于1指明了每个编码视频序列的编码图像都是只含帧宏块的编码帧,即FrameHeightInMbs = ( 2 − frame_mbs_only_flag ) * PicHeightInMapUnits ;


frame_cropping_flag:等于0表明不存在帧剪切偏移量,等于1表明在sps中下一个使用的帧剪切偏移量参数,即需要使用到frame_crop_left_offset、frame_crop_right_offset、frame_crop_top_offset、frame_crop_bottom_offset四个参数;

frame_crop_left_offset、frame_crop_right_offset、frame_crop_top_offset、frame_crop_bottom_offset:左右上下帧裁剪偏移量,需要根据chroma format计算实际的视频宽高;

chroma_format_idc:亮度取样对应的色度取样值,包括0~3,不存在时默认为1(即YUV420);

根据上述参数的定义说明,计算视频分辨率存在多种情况:1、需要判断是否包含宏片的编码帧或场;2、需要判断视频帧是否被裁剪;3、需要判断采样类型。因此代码大致如下:

  1. UINT pic_width_in_mbs_minus1 = ue(&bs);     //36位开始
  2. UINT pic_height_in_map_units_minus1 = ue(&bs);      //47
  3. UINT frame_mbs_only_flag = u(&bs, 1);
  4.  
  5. info->width = (INT)(pic_width_in_mbs_minus1 + 1) * 16;
  6. info->height = (INT)(2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1) * 16;
  7.  
  8. if (!frame_mbs_only_flag) {
  9.     u(&bs, 1);      //mb_adaptive_frame_field_flag
  10. }
  11.  
  12. u(&bs, 1);     //direct_8x8_inference_flag
  13. UINT frame_cropping_flag = u(&bs, 1);
  14. if (frame_cropping_flag) {
  15.     UINT frame_crop_left_offset = ue(&bs);
  16.     UINT frame_crop_right_offset = ue(&bs);
  17.     UINT frame_crop_top_offset = ue(&bs);
  18.     UINT frame_crop_bottom_offset= ue(&bs);
  19.     
  20.     //See 6.2 Source, decoded, and output picture formats
  21.     INT crop_unit_x = 1;
  22.     INT crop_unit_y = 2 - frame_mbs_only_flag;      //monochrome or 4:4:4
  23.     if (chroma_format_idc == 1) {   //4:2:0
  24.         crop_unit_x = 2;
  25.         crop_unit_y = 2 * (2 - frame_mbs_only_flag);
  26.     } else if (chroma_format_idc == 2) {    //4:2:2
  27.         crop_unit_x = 2;
  28.         crop_unit_y = 2 - frame_mbs_only_flag;
  29.     }
  30.     
  31.     info->width -= crop_unit_x * (frame_crop_left_offset + frame_crop_right_offset);
  32.     info->height -= crop_unit_y * (frame_crop_top_offset + frame_crop_bottom_offset);
  33. }


视频帧率(FPS)获取
视频帧率信息在SPS的VUI parameters syntax中,需要根据time_scale、fixed_frame_rate_flag计算得到:fps = time_scale / num_units_in_tick。但是需要判断参数timing_info_present_flag是否存在,若不存在表示FPS在信息流中无法获取。同时还存在另外一种情况:fixed_frame_rate_flag为1时,两个连续图像的HDR输出时间频率为单位,获取的fps是实际的2倍。

  1. UINT timing_info_present_flag = u(bs, 1);
  2. if (timing_info_present_flag) {
  3.     UINT num_units_in_tick = u(bs, 32);
  4.     UINT time_scale = u(bs, 32);
  5.     UINT fixed_frame_rate_flag = u(bs, 1);
  6.     
  7.     info->fps = (UINT)((float)time_scale / (float)num_units_in_tick);
  8.     if (fixed_frame_rate_flag) {
  9.         info->fps = info->fps/2;
  10.     }
  11. }


SPS解析代码

  1. H264ParseSPS.h
  2. //
  3. //  H264ParseSPS.h
  4. //
  5. //  Created by lzj<lizhijian_21@163.com> on 2018/7/6.
  6. //  Copyright © 2018年 LZJ. All rights reserved.
  7. //
  8. #ifndef H264ParseSPS_h
  9. #define H264ParseSPS_h
  10. #ifdef __cplusplus
  11. extern "C"
  12. {
  13. #endif
  14. #include <stdio.h>
  15.     
  16. typedef struct
  17. {
  18.     unsigned int profile_idc;
  19.     unsigned int level_idc;
  20.     
  21.     unsigned int width;
  22.     unsigned int height;
  23.     unsigned int fps;       //SPS中可能不包含FPS信息
  24. } sps_info_struct;
  25.     
  26. /**
  27.  解析SPS数据信息
  28.  @param data SPS数据内容,需要Nal类型为0x7数据的开始(比如:67 42 00 28 ab 40 22 01 e3 cb cd c0 80 80 a9 02)
  29.  @param dataSize SPS数据的长度
  30.  @param info SPS解析之后的信息数据结构体
  31.  @return success:1,fail:0
  32.  
  33.  */
  34. int h264_parse_sps(const unsigned char *data, unsigned int dataSize, sps_info_struct *info);
  35. #ifdef __cplusplus
  36. }
  37. #endif
  38. #endif /* H264ParseSPS_h */
  39. H264ParseSPS.c
  40. //
  41. //  H264ParseSPS.c
  42. //
  43. //  Created by lzj<lizhijian_21@163.com> on 2018/7/6.
  44. //  Copyright © 2018年 LZJ. All rights reserved.
  45. //
  46. //  See https://www.itu.int/rec/T-REC-H.264-201610-S
  47. //
  48.  
  49. #include "H264ParseSPS.h"
  50. #include <string.h>
  51. #include <stdlib.h>
  52. #include <math.h>
  53.  
  54. typedef unsigned char BYTE;
  55. typedef int INT;
  56. typedef unsigned int UINT;
  57.  
  58. typedef struct
  59. {
  60.     const BYTE *data;   //sps数据
  61.     UINT size;          //sps数据大小
  62.     UINT index;         //当前计算位所在的位置标记
  63. } sps_bit_stream;
  64.  
  65. /**
  66.  移除H264的NAL防竞争码(0x03)
  67.  @param data sps数据
  68.  @param dataSize sps数据大小
  69.  */
  70. static void del_emulation_prevention(BYTE *data, UINT *dataSize)
  71. {
  72.     UINT dataSizeTemp = *dataSize;
  73.     for (UINT i=0, j=0; i<(dataSizeTemp-2); i++) {
  74.         int val = (data[i]^0x0) + (data[i+1]^0x0) + (data[i+2]^0x3);    //检测是否是竞争码
  75.         if (val == 0) {
  76.             for (j=i+2; j<dataSizeTemp-1; j++) {    //移除竞争码
  77.                 data[j] = data[j+1];
  78.             }
  79.             
  80.             (*dataSize)--;      //data size1
  81.         }
  82.     }
  83. }
  84.  
  85. static void sps_bs_init(sps_bit_stream *bs, const BYTE *data, UINT size)
  86. {
  87.     if (bs) {
  88.         bs->data = data;
  89.         bs->size = size;
  90.         bs->index = 0;
  91.     }
  92. }
  93.  
  94. /**
  95.  是否已经到数据流最后
  96.  
  97.  @param bs sps_bit_stream数据
  98.  @return 1:yes,0no
  99.  */
  100. static INT eof(sps_bit_stream *bs)
  101. {
  102.     return (bs->index >= bs->size * 8);    //位偏移已经超出数据
  103. }
  104.  
  105. /**
  106.  读取从起始位开始的BitCount个位所表示的值
  107.  
  108.  @param bs sps_bit_stream数据
  109.  @param bitCount bit位个数(从低到高)
  110.  @return value
  111.  */
  112. static UINT u(sps_bit_stream *bs, BYTE bitCount)
  113. {
  114.     UINT val = 0;
  115.     for (BYTE i=0; i<bitCount; i++) {
  116.         val <<= 1;
  117.         if (eof(bs)) {
  118.             val = 0;
  119.             break;
  120.         } else if (bs->data[bs->index / 8] & (0x80 >> (bs->index % 8))) {     //计算index所在的位是否为1
  121.             val |= 1;
  122.         }
  123.         bs->index++;  //递增当前起始位(表示该位已经被计算,在后面的计算过程中不需要再次去计算所在的起始位索引,缺点:后面每个bit位都需要去位移)
  124.     }
  125.     
  126.     return val;
  127. }
  128.  
  129. /**
  130.  读取无符号哥伦布编码值(UE)
  131.  #2^LeadingZeroBits - 1 + (xxx)
  132.  @param bs sps_bit_stream数据
  133.  @return value
  134.  */
  135. static UINT ue(sps_bit_stream *bs)
  136. {
  137.     UINT zeroNum = 0;
  138.     while (u(bs, 1) == 0 && !eof(bs) && zeroNum < 32) {
  139.         zeroNum ++;
  140.     }
  141.     
  142.     return (UINT)((1 << zeroNum) - 1 + u(bs, zeroNum));
  143. }
  144.  
  145. /**
  146.  读取有符号哥伦布编码值(SE)
  147.  #(-1)^(k+1) * Ceil(k/2)
  148.  
  149.  @param bs sps_bit_stream数据
  150.  @return value
  151.  */
  152. INT se(sps_bit_stream *bs)
  153. {
  154.     INT ueVal = (INT)ue(bs);
  155.     double k = ueVal;
  156.     
  157.     INT seVal = (INT)ceil(k / 2);     //ceil:返回大于或者等于指定表达式的最小整数
  158.     if (ueVal % 2 == 0) {       //偶数取反,即(-1)^(k+1)
  159.         seVal = -seVal;
  160.     }
  161.     
  162.     return seVal;
  163. }
  164.  
  165. /**
  166.  视频可用性信息(Video usability information)解析
  167.  @param bs sps_bit_stream数据
  168.  @param info sps解析之后的信息数据及结构体
  169.  @see E.1.1 VUI parameters syntax
  170.  */
  171. void vui_para_parse(sps_bit_stream *bs, sps_info_struct *info)
  172. {
  173.     UINT aspect_ratio_info_present_flag = u(bs, 1);
  174.     if (aspect_ratio_info_present_flag) {
  175.         UINT aspect_ratio_idc = u(bs, 8);
  176.         if (aspect_ratio_idc == 255) {      //Extended_SAR
  177.             u(bs, 16);      //sar_width
  178.             u(bs, 16);      //sar_height
  179.         }
  180.     }
  181.     
  182.     UINT overscan_info_present_flag = u(bs, 1);
  183.     if (overscan_info_present_flag) {
  184.         u(bs, 1);       //overscan_appropriate_flag
  185.     }
  186.     
  187.     UINT video_signal_type_present_flag = u(bs, 1);
  188.     if (video_signal_type_present_flag) {
  189.         u(bs, 3);       //video_format
  190.         u(bs, 1);       //video_full_range_flag
  191.         UINT colour_description_present_flag = u(bs, 1);
  192.         if (colour_description_present_flag) {
  193.             u(bs, 8);       //colour_primaries
  194.             u(bs, 8);       //transfer_characteristics
  195.             u(bs, 8);       //matrix_coefficients
  196.         }
  197.     }
  198.     
  199.     UINT chroma_loc_info_present_flag = u(bs, 1);
  200.     if (chroma_loc_info_present_flag) {
  201.         ue(bs);     //chroma_sample_loc_type_top_field
  202.         ue(bs);     //chroma_sample_loc_type_bottom_field
  203.     }
  204.  
  205.     UINT timing_info_present_flag = u(bs, 1);
  206.     if (timing_info_present_flag) {
  207.         UINT num_units_in_tick = u(bs, 32);
  208.         UINT time_scale = u(bs, 32);
  209.         UINT fixed_frame_rate_flag = u(bs, 1);
  210.         
  211.         info->fps = (UINT)((float)time_scale / (float)num_units_in_tick);
  212.         if (fixed_frame_rate_flag) {
  213.             info->fps = info->fps/2;
  214.         }
  215.     }
  216.     
  217.     UINT nal_hrd_parameters_present_flag = u(bs, 1);
  218.     if (nal_hrd_parameters_present_flag) {
  219.         //hrd_parameters()  //see E.1.2 HRD parameters syntax
  220.     }
  221.     
  222.     //后面代码需要hrd_parameters()函数接口实现才有用
  223.     UINT vcl_hrd_parameters_present_flag = u(bs, 1);
  224.     if (vcl_hrd_parameters_present_flag) {
  225.         //hrd_parameters()
  226.     }
  227.     if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
  228.         u(bs, 1);   //low_delay_hrd_flag
  229.     }
  230.     
  231.     u(bs, 1);       //pic_struct_present_flag
  232.     UINT bitstream_restriction_flag = u(bs, 1);
  233.     if (bitstream_restriction_flag) {
  234.         u(bs, 1);   //motion_vectors_over_pic_boundaries_flag
  235.         ue(bs);     //max_bytes_per_pic_denom
  236.         ue(bs);     //max_bits_per_mb_denom
  237.         ue(bs);     //log2_max_mv_length_horizontal
  238.         ue(bs);     //log2_max_mv_length_vertical
  239.         ue(bs);     //max_num_reorder_frames
  240.         ue(bs);     //max_dec_frame_buffering
  241.     }
  242. }
  243.  
  244. //See 7.3.1 NAL unit syntax
  245. //See 7.3.2.1.1 Sequence parameter set data syntax
  246. INT h264_parse_sps(const BYTE *data, UINT dataSize, sps_info_struct *info)
  247. {
  248.     if (!data || dataSize <= 0 || !info) return 0;
  249.     INT ret = 0;
  250.     
  251.     BYTE *dataBuf = malloc(dataSize);
  252.     memcpy(dataBuf, data, dataSize);        //重新拷贝一份数据,防止移除竞争码时对原数据造成影响
  253.     del_emulation_prevention(dataBuf, &dataSize);
  254.  
  255.     sps_bit_stream bs = {0};
  256.     sps_bs_init(&bs, dataBuf, dataSize);   //初始化SPS数据流结构体
  257.     
  258.     u(&bs, 1);      //forbidden_zero_bit
  259.     u(&bs, 2);      //nal_ref_idc
  260.     UINT nal_unit_type = u(&bs, 5);
  261.  
  262.     if (nal_unit_type == 0x7) {     //Nal SPS Flag
  263.         info->profile_idc = u(&bs, 8);
  264.         u(&bs, 1);      //constraint_set0_flag
  265.         u(&bs, 1);      //constraint_set1_flag
  266.         u(&bs, 1);      //constraint_set2_flag
  267.         u(&bs, 1);      //constraint_set3_flag
  268.         u(&bs, 1);      //constraint_set4_flag
  269.         u(&bs, 1);      //constraint_set4_flag
  270.         u(&bs, 2);      //reserved_zero_2bits
  271.         info->level_idc = u(&bs, 8);
  272.         
  273.         ue(&bs);    //seq_parameter_set_id
  274.         
  275.         UINT chroma_format_idc = 1;     //摄像机出图大部分格式是4:2:0
  276.         if (info->profile_idc == 100 || info->profile_idc == 110 || info->profile_idc == 122 ||
  277.             info->profile_idc == 244 || info->profile_idc == 44 || info->profile_idc == 83 ||
  278.             info->profile_idc == 86 || info->profile_idc == 118 || info->profile_idc == 128 ||
  279.             info->profile_idc == 138 || info->profile_idc == 139 || info->profile_idc == 134 || info->profile_idc == 135) {
  280.             chroma_format_idc = ue(&bs);
  281.             if (chroma_format_idc == 3) {
  282.                 u(&bs, 1);      //separate_colour_plane_flag
  283.             }
  284.             
  285.             ue(&bs);        //bit_depth_luma_minus8
  286.             ue(&bs);        //bit_depth_chroma_minus8
  287.             u(&bs, 1);      //qpprime_y_zero_transform_bypass_flag
  288.             UINT seq_scaling_matrix_present_flag = u(&bs, 1);
  289.             if (seq_scaling_matrix_present_flag) {
  290.                 UINT seq_scaling_list_present_flag[8] = {0};
  291.                 for (INT i=0; i<((chroma_format_idc != 3)?8:12); i++) {
  292.                     seq_scaling_list_present_flag[i] = u(&bs, 1);
  293.                     if (seq_scaling_list_present_flag[i]) {
  294.                         if (i < 6) {    //scaling_list(ScalingList4x4[i], 16, UseDefaultScalingMatrix4x4Flag[i])
  295.                         } else {    //scaling_list(ScalingList8x8[i − 6], 64, UseDefaultScalingMatrix8x8Flag[i − 6] )
  296.                         }
  297.                     }
  298.                 }
  299.             }
  300.         }
  301.         
  302.         ue(&bs);        //log2_max_frame_num_minus4
  303.         UINT pic_order_cnt_type = ue(&bs);
  304.         if (pic_order_cnt_type == 0) {
  305.             ue(&bs);        //log2_max_pic_order_cnt_lsb_minus4
  306.         } else if (pic_order_cnt_type == 1) {
  307.             u(&bs, 1);      //delta_pic_order_always_zero_flag
  308.             se(&bs);        //offset_for_non_ref_pic
  309.             se(&bs);        //offset_for_top_to_bottom_field
  310.             
  311.             UINT num_ref_frames_in_pic_order_cnt_cycle = ue(&bs);
  312.             INT *offset_for_ref_frame = (INT *)malloc((UINT)num_ref_frames_in_pic_order_cnt_cycle * sizeof(INT));
  313.             for (INT i = 0; i<num_ref_frames_in_pic_order_cnt_cycle; i++) {
  314.                 offset_for_ref_frame[i] = se(&bs);
  315.             }
  316.             free(offset_for_ref_frame);
  317.         }
  318.         
  319.         ue(&bs);      //max_num_ref_frames
  320.         u(&bs, 1);      //gaps_in_frame_num_value_allowed_flag
  321.         
  322.         UINT pic_width_in_mbs_minus1 = ue(&bs);     //36位开始
  323.         UINT pic_height_in_map_units_minus1 = ue(&bs);      //47
  324.         UINT frame_mbs_only_flag = u(&bs, 1);
  325.         
  326.         info->width = (INT)(pic_width_in_mbs_minus1 + 1) * 16;
  327.         info->height = (INT)(2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1) * 16;
  328.         
  329.         if (!frame_mbs_only_flag) {
  330.             u(&bs, 1);      //mb_adaptive_frame_field_flag
  331.         }
  332.         
  333.         u(&bs, 1);     //direct_8x8_inference_flag
  334.         UINT frame_cropping_flag = u(&bs, 1);
  335.         if (frame_cropping_flag) {
  336.             UINT frame_crop_left_offset = ue(&bs);
  337.             UINT frame_crop_right_offset = ue(&bs);
  338.             UINT frame_crop_top_offset = ue(&bs);
  339.             UINT frame_crop_bottom_offset= ue(&bs);
  340.             
  341.             //See 6.2 Source, decoded, and output picture formats
  342.             INT crop_unit_x = 1;
  343.             INT crop_unit_y = 2 - frame_mbs_only_flag;      //monochrome or 4:4:4
  344.             if (chroma_format_idc == 1) {   //4:2:0
  345.                 crop_unit_x = 2;
  346.                 crop_unit_y = 2 * (2 - frame_mbs_only_flag);
  347.             } else if (chroma_format_idc == 2) {    //4:2:2
  348.                 crop_unit_x = 2;
  349.                 crop_unit_y = 2 - frame_mbs_only_flag;
  350.             }
  351.             
  352.             info->width -= crop_unit_x * (frame_crop_left_offset + frame_crop_right_offset);
  353.             info->height -= crop_unit_y * (frame_crop_top_offset + frame_crop_bottom_offset);
  354.         }
  355.         
  356.         UINT vui_parameters_present_flag = u(&bs, 1);
  357.         if (vui_parameters_present_flag) {
  358.             vui_para_parse(&bs, info);
  359.         }
  360.      
  361.         ret = 1;
  362.     }
  363.     free(dataBuf);
  364.     
  365.     return ret;
  366. }


代码中部分未用到的参数并没有获取并赋值,比如:u(&bs, 1);      //forbidden_zero_bit。如需获取相应的参数,只需将注释后面对应的变量值进行赋值即可,如:UINT forbidden_zero_bit = u(&bs, 1);
h264_parse_sps接口中sps数据需要第一个字节以Nal类型为0x7作为开始,比如:67 42 00 28 ab 40 22 01 e3 cb cd c0 80 80 a9 02,解析得到的宽高为1080*1920,fps为0。
 

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/722319
推荐阅读