首页 > 其他分享 >H264 码流分析

H264 码流分析

时间:2024-03-30 21:23:12浏览次数:23  
标签:码流 分析 set get H264 BsReadU1 sps int public

内容
1、 H264 码流分析: 一帧可能由多个NALU组成,由Slice片区类型不同定义成不同的NALU 单元,每个片区之间用0001 隔离,H264纯数据不允许出现连续三个字节为0,在第二个后面插入03,00 00 30 00 表示00 00 00
2、 片区类型的定义为:首位 & 0X1F(取低5位)
1:表示 非I帧,具体是P还是B帧不知道
5:表示 I帧
6:表示 SEI
7:表示 SPS
8:表示 PPS
例如:
39 -> 7 -> SPS
40 -> 8 -> PPS
6 -> 6 -> SEI
37 -> 5 -> I 帧


3、 NALU = NALU Header + NALU Body(通常是RBSP(Raw Byte Sequence Payload 原始字节序列载荷)数据)
NALU Header = SPS + PPS + I Slice
NALU Body = P/B Slice

4、 1 SPS + 1PPS + 1 SEI + 1 I帧 + N(P/B)帧
SPS(Sequence Parameter Set):SPS包含了视频序列的参数和配置信息,如编码标准、图像分辨率、帧率、色彩空间等。SPS对于整个视频序列都是通用的,一般只需要发送一次,在视频流的开始或关键帧附近。解码器需要使用SPS来正确解码视频数据。 主要记录了编码视频的Profile、level、图像宽高等
PPS(Picture Parameter Set):PPS包含了图像特定的参数和配置信息,如量化矩阵、图像类型等。与SPS不同,PPS可能会针对每一帧图像都发送一次,它提供了用于该帧的特定设置,允许视频序列中不同的图像有不同的参数配置。主要记录编码数据所依赖的参数,如参考帧,图像序列计算方法等。
SEI(Supplemental Enhancement Information):SEI用于向视频码流中插入一些额外的、与视频内容相关的信息,比如图像标签、时间戳、颜色参数等。SEI数据是一些元数据信息,通常用于指示对视频进行特殊处理或详细描述视频内容。
SPS包含了视频序列的基本参数,PPS包含了图像特定的参数,而SEI用于插入额外的元数据信息。这三者一起构成了视频编码过程中必要的参数和附加信息,以便在解码和处理视频数据时能够正确地还原和显示视频内容

解析码流数据:

真正 Sps 数据sequence: 从39 100 到...129 定义为 。在解析的时候跳过第一位 39 ,因为39 是sps 定义sps类型字节 

var sequenceParameterSet = sequence.Skip(1).ToArray();

 /// <summary>
 ///比特流读取状态
 /// </summary>
 internal unsafe struct BitStreamReader
 {
     /// <summary>
     /// 比特流的起始位置
     /// </summary>
     public byte* Start;
     /// <summary>
     /// 当前的读取位置
     /// </summary>
     public byte* CurrentPosition;
     /// <summary>
     /// 比特流的结束位置
     /// </summary>
     public byte* End;
     /// <summary>
     /// 当前位置后剩余的比特数
     /// </summary>
     public int BitsRemaining;
 }
  internal  unsafe struct Sps
  {
      public Sps() { }
      public int ProfileIdc { get; set; }
      public int ConstraintSet0Flag { get; set; }
      public int ConstraintSet1Flag { get; set; }
      public int ConstraintSet2Flag { get; set; }
      public int ConstraintSet3Flag { get; set; }
      public int ConstraintSet4Flag { get; set; }
      public int ConstraintSet5Flag { get; set; }
      public int ReservedZero2Bits { get; set; }
      public int LevelIdc { get; set; }
      public int SeqParameterSetId { get; set; }
      public int ChromaFormatIdc { get; set; }
      public int ResidualColourTransformFlag { get; set; }
      public int BitDepthLumaMinus8 { get; set; }
      public int BitDepthChromaMinus8 { get; set; }
      public int QpprimeYZeroTransformBypassFlag { get; set; }
      public int SeqScalingMatrixPresentFlag { get; set; }
      public int[] SeqScalingListPresentFlag{ get; set; } = new int[8];
      public int[][] ScalingList4X4 { get; set; } = new int[6][];
      public int[] UseDefaultScalingMatrix4X4Flag { get; set; } = new int[6];
      public int[][] ScalingList8X8 { get; set; } = new int[6][];
      public int[] UseDefaultScalingMatrix8x8Flag{ get; set; } = new int[3];
      public int Log2MaxFrameNumMinus4 { get; set; }
      public int PicOrderCntType { get; set; }
      public int Log2MaxPicOrderCntLsbMinus4 { get; set; }
      public int DeltaPicOrderAlwaysZeroFlag { get; set; }
      public int OffsetForNonRefPic { get; set; }
      public int OffsetForTopToBottomField { get; set; }
      public int NumRefFramesInPicOrderCntCycle { get; set; }
      public int[] OffsetForRefFrame { get; set; } = new int[256];
      public int NumRefFrames { get; set; }
      public int GapsInFrameNumValueAllowedFlag { get; set; }
      public int PicWidthInMbsMinus1 { get; set; }
      public int PicHeightInMapUnitsMinus1 { get; set; }
      public int FrameMbsOnlyFlag { get; set; }
      public int MbAdaptiveFrameFieldFlag { get; set; }
      public int Direct8X8InferenceFlag { get; set; }
      public int FrameCroppingFlag { get; set; }
      public int FrameCropLeftOffset { get; set; }
      public int FrameCropRightOffset { get; set; }
      public int FrameCropTopOffset { get; set; }
      public int FrameCropBottomOffset { get; set; }
      public int VuiParametersPresentFlag { get; set; }
      public Vui Vui { get; set; } = new Vui();
      public Hrd Hrd { get; set; } = new Hrd();
  }

  internal struct Vui
  {
      public int AspectRatioInfoPresentFlag { get; set; }
      public int AspectRatioIdc { get; set; }
      public int SarWidth { get; set; }
      public int SarHeight { get; set; }
      public int OverscanInfoPresentFlag { get; set; }
      public int OverscanAppropriateFlag { get; set; }
      public int VideoSignalTypePresentFlag { get; set; }
      public int VideoFormat { get; set; }
      public int VideoFullRangeFlag { get; set; }
      public int ColourDescriptionPresentFlag { get; set; }
      public int ColourPrimaries { get; set; }
      public int TransferCharacteristics { get; set; }
      public int MatrixCoefficients { get; set; }
      public int ChromaLocInfoPresentFlag { get; set; }
      public int ChromaSampleLocTypeTopField { get; set; }
      public int ChromaSampleLocTypeBottomField { get; set; }
      public int TimingInfoPresentFlag { get; set; }
      public int NumUnitsInTick { get; set; }
      public int TimeScale { get; set; }
      public int FixedFrameRateFlag { get; set; }
      public int NalHrdParametersPresentFlag { get; set; }
      public int VclHrdParametersPresentFlag { get; set; }
      public int LowDelayHrdFlag { get; set; }
      public int PicStructPresentFlag { get; set; }
      public int BitStreamRestrictionFlag { get; set; }
      public int MotionVectorsOverPicBoundariesFlag { get; set; }
      public int MaxBytesPerPicDenom { get; set; }
      public int MaxBitsPerMbDenom { get; set; }
      public int Log2MaxMvLengthHorizontal { get; set; }
      public int Log2MaxMvLengthVertical { get; set; }
      public int NumReorderFrames { get; set; }
      public int MaxDecFrameBuffering { get; set; }
  }

  internal struct Hrd
  {
      public Hrd() { }
      public int CpbCntMinus1 { get; set; }
      public int BitRateScale { get; set; }
      public int CpbSizeScale { get; set; }
      public int[] BitRateValueMinus1 { get; set; } = new int[32];
      public int[] CpbSizeValueMinus1 { get; set; } = new int[32];
      public int[] CbrFlag { get; set; } = new int[32];
      public int InitialCpbRemovalDelayLengthMinus1 { get; set; }
      public int CpbRemovalDelayLengthMinus1 { get; set; }
      public int DpbOutputDelayLengthMinus1 { get; set; }
      public int TimeOffsetLength { get; set; }
  }
  internal unsafe class BitStreamAnalyze
  {
      /// <summary>
      /// 初始化比特流
      /// </summary>
      /// <param name="buf">比特流指针</param>
      /// <param name="size">字节长度</param>
      public static BitStreamReader BitStreamInit(byte* buf, int size)
      {
          BitStreamReader b = new BitStreamReader
          {
              Start = buf,
              CurrentPosition = buf,
              End = buf + size,
              BitsRemaining = 8
          };
          return b;
      }

      /// <summary>
      /// 读起Sps
      /// </summary>
      public static Sps ReadSeqParameterSetRbsp(BitStreamReader* b)
      {
          int i;
          var sps = new Sps
          {
              ChromaFormatIdc = 1,
              ProfileIdc = BsReadU8(b),
              ConstraintSet0Flag = BsReadU1(b),
              ConstraintSet1Flag = BsReadU1(b),
              ConstraintSet2Flag = BsReadU1(b),
              ConstraintSet3Flag = BsReadU1(b),
              ConstraintSet4Flag = BsReadU1(b),
              ConstraintSet5Flag = BsReadU1(b),
              ReservedZero2Bits = BsReadU(b, 2),
              LevelIdc = BsReadU8(b),
              SeqParameterSetId = BsReadUe(b)
          };
          if (sps.ProfileIdc == 100 || sps.ProfileIdc == 110 || sps.ProfileIdc == 122 || sps.ProfileIdc == 144)
          {
              sps.ChromaFormatIdc = BsReadUe(b);
              if (sps.ChromaFormatIdc == 3)
              {
                  sps.ResidualColourTransformFlag = BsReadU1(b);
              }
              sps.BitDepthLumaMinus8 = BsReadUe(b);
              sps.BitDepthChromaMinus8 = BsReadUe(b);
              sps.QpprimeYZeroTransformBypassFlag = BsReadU1(b);
              sps.SeqScalingMatrixPresentFlag = BsReadU1(b);
              if (sps.SeqScalingMatrixPresentFlag !=0 )
              {
                  for (i = 0; i < 8; i++)
                  {
                      sps.SeqScalingListPresentFlag[i] = BsReadU1(b);
                      if (sps.SeqScalingListPresentFlag[i] == 0) continue;
                      if (i < 6)
                          ReadScalingList(b, sps.ScalingList4X4[i], 16, sps.UseDefaultScalingMatrix4X4Flag[i]);
                      else
                          ReadScalingList(b, sps.ScalingList8X8[i - 6], 64, sps.UseDefaultScalingMatrix8x8Flag[i - 6]);
                  }
              }
          }
          sps.Log2MaxFrameNumMinus4 = BsReadUe(b);
          sps.PicOrderCntType = BsReadUe(b);
          if (sps.PicOrderCntType == 0)
          {
              sps.Log2MaxPicOrderCntLsbMinus4 = BsReadUe(b);
          }
          else if (sps.PicOrderCntType == 1)
          {
              sps.DeltaPicOrderAlwaysZeroFlag = BsReadU1(b);
              sps.OffsetForNonRefPic = BsReadSe(b);
              sps.OffsetForTopToBottomField = BsReadSe(b);
              sps.NumRefFramesInPicOrderCntCycle = BsReadUe(b);
              for (i = 0; i < sps.NumRefFramesInPicOrderCntCycle; i++)
              {
                  sps.OffsetForRefFrame[i] = BsReadSe(b);
              }
          }
          sps.NumRefFrames = BsReadUe(b);
          sps.GapsInFrameNumValueAllowedFlag = BsReadU1(b);
          sps.PicWidthInMbsMinus1 = BsReadUe(b);
          sps.PicHeightInMapUnitsMinus1 = BsReadUe(b);
          sps.FrameMbsOnlyFlag = BsReadU1(b);
          if (sps.FrameMbsOnlyFlag == 0)
          {
              sps.MbAdaptiveFrameFieldFlag = BsReadU1(b);
          }
          sps.Direct8X8InferenceFlag = BsReadU1(b);
          sps.FrameCroppingFlag = BsReadU1(b);
          if (sps.FrameCroppingFlag != 0)
          {
              sps.FrameCropLeftOffset = BsReadUe(b);
              sps.FrameCropRightOffset = BsReadUe(b);
              sps.FrameCropTopOffset = BsReadUe(b);
              sps.FrameCropBottomOffset = BsReadUe(b);
          }
          sps.VuiParametersPresentFlag = BsReadU1(b);
          if (sps.VuiParametersPresentFlag != 0)
          {
              ReadVuiParameters(sps,b);
          }
          ReadRbspTrailingBits(sps,b);
          return sps;
      }

      #region 私有方法
      private static  int BsReadU8(BitStreamReader* b)
      {
          if (b->BitsRemaining == 8 && !BsEof(b)) 
          {
              int r = b->CurrentPosition[0];
              b->CurrentPosition++;
              return r;
          }
          return BsReadU(b, 8);
      }

      private static bool BsEof(BitStreamReader* b) => b->CurrentPosition >= b->End;

      private static  int BsReadU(BitStreamReader* b, int n)
      {
          int r = 0;
          int i;
          for (i = 0; i < n; i++)
          {
              r |= (BsReadU1(b) << (n - i - 1));
          }
          return r;
      }

      private static  int  BsReadU1(BitStreamReader* b)
      {
          var r = 0;
          b->BitsRemaining--;
          if (!BsEof(b))
          {
              r = ((*(b->CurrentPosition)) >> b->BitsRemaining) & 0x01;
          }

          if (b->BitsRemaining == 0)
          {
              b->CurrentPosition++;
              b->BitsRemaining = 8;
          }
          return r;
      }

      private static  int BsReadUe(BitStreamReader* b)
      {
          int r = 0;
          int i = 0;
          while ((BsReadU1(b) == 0) && (i < 32) && (!BsEof(b)))
          {
              i++;
          }
          r = BsReadU(b, i);
          r += (1 << i) - 1;
          return r;
      }

      private static void ReadScalingList(BitStreamReader* b, int[] scalingList, int sizeOfScalingList,int useDefaultScalingMatrixFlag)
      {
          if (scalingList == null) return;
          int j;
          int lastScale = 8;
          int nextScale = 8;
          for (j = 0; j < sizeOfScalingList; j++)
          {
              if (nextScale != 0)
              {
                  int deltaScale = BsReadSe(b);
                  nextScale = (lastScale + deltaScale + 256) % 256;
                  var b1 = j == 0 && nextScale == 0;
                  useDefaultScalingMatrixFlag = b1 ? 1 : 0;
              }
              scalingList[j] = (nextScale == 0) ? lastScale : nextScale;
              lastScale = scalingList[j];
          }
      }

      private static  int BsReadSe(BitStreamReader* b)
      {
          int  r = BsReadUe(b);
          if ((r & 0x01 ) !=0)
              r = (r + 1) / 2;
          else
              r = -(r / 2);
          return r;
      }

      private static void ReadVuiParameters(Sps sps, BitStreamReader* b)
      {
          var spsVui = sps.Vui;
          spsVui.AspectRatioInfoPresentFlag = BsReadU1(b);
          if (spsVui.AspectRatioInfoPresentFlag !=0)
          {
              spsVui.AspectRatioIdc = BsReadU8(b);
              int sarExtended = 255; 
              if (spsVui.AspectRatioIdc == sarExtended)
              {
                  spsVui.SarWidth = BsReadU(b, 16);
                  spsVui.SarHeight = BsReadU(b, 16);
              }
          }
          spsVui.OverscanInfoPresentFlag = BsReadU1(b);
          if (spsVui.OverscanInfoPresentFlag !=0)
          {
              spsVui.OverscanAppropriateFlag = BsReadU1(b);
          }
          spsVui.VideoSignalTypePresentFlag = BsReadU1(b);
          if (spsVui.VideoSignalTypePresentFlag != 0)
          {
              spsVui.VideoFormat = BsReadU(b, 3);
              spsVui.VideoFullRangeFlag = BsReadU1(b);
              spsVui.ColourDescriptionPresentFlag = BsReadU1(b);
              if (spsVui.ColourDescriptionPresentFlag != 0)
              {
                  spsVui.ColourPrimaries = BsReadU8(b);
                  spsVui.TransferCharacteristics = BsReadU8(b);
                  spsVui.MatrixCoefficients = BsReadU8(b);
              }
          }
          spsVui.ChromaLocInfoPresentFlag = BsReadU1(b);
          if (spsVui.ChromaLocInfoPresentFlag !=0)
          {
              spsVui.ChromaSampleLocTypeTopField = BsReadUe(b);
              spsVui.ChromaSampleLocTypeBottomField = BsReadUe(b);
          }
          spsVui.TimingInfoPresentFlag = BsReadU1(b);
          if (spsVui.TimingInfoPresentFlag != 0)
          {
              spsVui.NumUnitsInTick = BsReadU(b, 32);
              spsVui.TimeScale = BsReadU(b, 32);
              spsVui.FixedFrameRateFlag = BsReadU1(b);
          }
          spsVui.NalHrdParametersPresentFlag = BsReadU1(b);
          if (spsVui.NalHrdParametersPresentFlag != 0)
          {
              ReadHrdParameters(sps, b);
          }
          spsVui.VclHrdParametersPresentFlag = BsReadU1(b);
          if (spsVui.VclHrdParametersPresentFlag != 0)
          {
              ReadHrdParameters(sps, b);
          }
          if (spsVui.NalHrdParametersPresentFlag  != 0 || spsVui.VclHrdParametersPresentFlag != 0)
          {
              spsVui.LowDelayHrdFlag = BsReadU1(b);
          }
          spsVui.PicStructPresentFlag = BsReadU1(b);
          spsVui.BitStreamRestrictionFlag = BsReadU1(b);
          if (spsVui.BitStreamRestrictionFlag != 0)
          {
              spsVui.MotionVectorsOverPicBoundariesFlag = BsReadU1(b);
              spsVui.MaxBytesPerPicDenom = BsReadUe(b);
              spsVui.MaxBitsPerMbDenom = BsReadUe(b);
              spsVui.Log2MaxMvLengthHorizontal = BsReadUe(b);
              spsVui.Log2MaxMvLengthVertical = BsReadUe(b);
              spsVui.NumReorderFrames = BsReadUe(b);
              spsVui.MaxDecFrameBuffering = BsReadUe(b);
          }
      }

      private static void ReadHrdParameters(Sps sps, BitStreamReader* b)
      {
          var spsHrd = sps.Hrd;
          spsHrd.CpbCntMinus1 = BsReadUe(b);
          spsHrd.BitRateScale = BsReadU(b, 4);
          spsHrd.CpbSizeScale = BsReadU(b, 4);
          for (var schedSelIdx = 0; schedSelIdx <= spsHrd.CpbCntMinus1; schedSelIdx++)
          {
              spsHrd.BitRateValueMinus1[schedSelIdx] = BsReadUe(b);
              spsHrd.CpbSizeValueMinus1[schedSelIdx] = BsReadUe(b);
              spsHrd.CbrFlag[schedSelIdx] = BsReadU1(b);
          }
          spsHrd.InitialCpbRemovalDelayLengthMinus1 = BsReadU(b, 5);
          spsHrd.CpbRemovalDelayLengthMinus1 = BsReadU(b, 5);
          spsHrd.DpbOutputDelayLengthMinus1 = BsReadU(b, 5);
          spsHrd.TimeOffsetLength = BsReadU(b, 5);
      }

      private static  void ReadRbspTrailingBits(Sps sps, BitStreamReader* b)
      {
          int rbspStopOneBit = BsReadU1(b); // equal to 1
          while (!BsByteAligned(b))
          {
              int rbspAlignmentZeroBit = BsReadU1(b); // equal to 0
          }
      }

      private static bool BsByteAligned(BitStreamReader* b) => b->BitsRemaining == 8;
      #endregion
  }

调用解析代码:

 unsafe
 {
     var sequenceParameterSet = sequence.Skip(1).ToArray();
     fixed (byte* p = sequenceParameterSet)
     {
         var bsT = BitStreamAnalyze.BitStreamInit(p, h264.LengthOfSps-1);
         var sps = BitStreamAnalyze.ReadSeqParameterSetRbsp(&bsT);
         widthSource = (sps.PicWidthInMbsMinus1 + 1) * 16;
         heightSource = (sps.PicHeightInMapUnitsMinus1 + 1) * 16;
     }
 }

 

参考资料:
1 https://blog.csdn.net/weixin_53762042/article/details/131267410
2 https://blog.csdn.net/oqqHuTu12345678/article/details/128221209
3 http://blog.csdn.net/leixiaohua1020

h264 码流解析项目
https://gitee.com/xgdu/H264_Analysis.git

标签:码流,分析,set,get,H264,BsReadU1,sps,int,public
From: https://www.cnblogs.com/terryK/p/18106040

相关文章

  • 慢速 HTTP 拒绝服务: 分析利用和缓解
    慢速HTTP拒绝服务:分析、利用和缓解   慢速HTTP攻击SlowHTTPDoSAttack基于这样一个事实,即HTTP协议在设计上要求服务器在处理请求之前完全接收请求。如果HTTP请求未完成,或者传输速率很低,服务器就会一直占用资源等待其他数据。如果服务器占用过多资源,可能会导致目标......
  • 毕业设计:基于python的药品销售数据分析可视化系统 大数据
    目录前言课题背景和意义实现技术思路一、算法理论基础1.1 ETL技术1.2OLAP技术1.3数据可视化二、 数据集三、实验及结果分析3.1 实验环境搭建3.2 模型训练最后前言  ......
  • sql 注入的类型之 post 基于错误的注入(sqllib靶场less-11-12)(通过burpusite分析)
      post注入和get注入一样,都是基于数据库没有对语句进行足够多的过滤,导致用户可以直接在url上执行sql语句。这两基本上没区别,但是基于post的注入在真实情况下会比get的多得多,最典型的post注入就是万能密码万能密码万能密码便是post注入的一种(也是sql注入),其原理也是因为后端......
  • 线程池-2:runWorker分析-1
    为何runWorker中在task被当前worker中的当前线程获取到准备执行task时需要进行worker.lock()?如下图:1、某个worker中的run逻辑只会被worker中包装的线程进行执行;2、按理说:不会存在多个线程并发执行同一个worker中的runWorker()逻辑,那么为什么需要在当前线程已经获取到task......
  • 35.网络游戏逆向分析与漏洞攻防-游戏网络通信数据解析-登录成功数据包内容分析
    免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!如果看不懂、不知道现在做的什么,那就跟着做完看效果内容参考于:易道云信息技术研究院VIP课上一个内容:34.登录数据包的监视与模拟首先登陆游戏,到角色选择界面,如下图,可以看到这个数据包很大2421个字节首先确定......
  • 【机器学习】数据探索(Data Exploration)---数据质量和数据特征分析
    一、引言  在机器学习项目中,数据探索是至关重要的一步。它不仅是模型构建的基础,还是确保模型性能稳定、预测准确的关键。数据探索的过程中,数据质量和数据特征分析占据了核心地位。数据质量直接关系到模型能否从数据中提取有效信息,而数据特征分析则决定了模型能否准确捕捉......
  • openGauss 慢SQL根因分析
    慢SQL根因分析可获得性本特性自openGauss3.0.0开始引入。特性简介慢SQL一直是数据运维中的痛点问题,如何有效诊断慢SQL根因是当前一大难题,工具结合openGauss自身特点融合了现网DBA慢SQL诊断经验,该工具可以支持慢SQL根因15+,能同时按照可能性大小输出多个根因并提供针对性的建议......
  • openGauss 高级分析函数支持
    高级分析函数支持可获得性本特性自openGauss1.1.0版本开始引入。特性简介无。客户价值我们提供窗口函数来进行数据高级分析处理。窗口函数将一个表中的数据进行预先分组,每一行属于一个特定的组,然后在这个组上进行一系列的关联分析计算。这样可以挖掘出每一个元组在这个集合......
  • openGauss 分布式分析能力
    分布式分析能力可获得性本特性自openGauss3.1.0版本开始引入。特性简介基于openLookeng实现分布式分析能力,与shardingsphere配合openGauss组成HTAP数据库。客户价值通过openLookeng快速实现海量数据分析。特性描述openLookeng复用shardingsphere中间件的分库分表能力,使op......
  • 数值分析复习:Newton-Cotes求积公式及复合求积公式
    文章目录1.中矩形公式2.梯形公式3.Simpson(辛普森)公式4.Newton-Cotes(牛顿-科特斯)求积公式5.各种求积公式的性质6.复合求积公式本篇文章适合个人复习翻阅,不建议新手入门使用本专栏:数值分析复习的前置知识主要有:数学分析、高等代数、泛函分析1.中矩形公式......