H26xParsers.cpp
Go to the documentation of this file.
1 #include "H26xParsers.hpp"
2 
3 #include <cmath>
4 #include <tuple>
5 
6 namespace dai {
7 namespace utility {
8 
9 template <typename T>
10 struct H26xParser {
11  protected:
12  virtual void parseNal(const std::vector<std::uint8_t>& bs, unsigned int start, std::vector<SliceType>& out) = 0;
13  std::vector<SliceType> parseBytestream(const std::vector<std::uint8_t>& bs, bool breakOnFirst);
14 
15  public:
16  static std::vector<SliceType> getTypes(const std::vector<std::uint8_t>& bs, bool breakOnFirst);
17  virtual ~H26xParser() = default;
18 };
19 
20 struct H264Parser : H26xParser<H264Parser> {
21  void parseNal(const std::vector<std::uint8_t>& bs, unsigned int start, std::vector<SliceType>& out);
22 };
23 
24 struct H265Parser : H26xParser<H265Parser> {
25  unsigned int nalUnitType = 0; // In NAL header
26  unsigned int dependentSliceSegmentsEnabledFlag = 0; // In picture parameter set
27  unsigned int numExtraSliceHeaderBits = 0; // In picture parameter set
28  // Getting the length of slice_segment address
29  unsigned int picWidthInLumaSamples = 0; // In sequence parameter set
30  unsigned int picHeightInLumaSamples = 0; // In sequence parameter set
31  unsigned int chromaFormatIdc = 0; // In sequence parameter set
32  unsigned int log2DiffMaxMinLumaCodingBlockSize = 0; // In sequence parameter set
33  unsigned int log2MinLumaCodingBlockSizeMinus3 = 0; // In sequence parameter set
34 
35  void parseNal(const std::vector<std::uint8_t>& bs, unsigned int start, std::vector<SliceType>& out);
36 };
37 
38 typedef unsigned int uint;
39 typedef unsigned long ulong;
40 typedef const std::vector<std::uint8_t> buf;
41 
43  switch(p) {
44  case Profile::H264:
45  switch(num) {
46  case 0:
47  case 5:
48  return SliceType::P;
49  case 1:
50  case 6:
51  return SliceType::B;
52  case 2:
53  case 7:
54  return SliceType::I;
55  case 3:
56  case 8:
57  return SliceType::SP;
58  case 4:
59  case 9:
60  return SliceType::SI;
61  default:
62  return SliceType::Unknown;
63  }
64  case Profile::H265:
65  switch(num) {
66  case 0:
67  return SliceType::B;
68  case 1:
69  return SliceType::P;
70  case 2:
71  return SliceType::I;
72  default:
73  return SliceType::Unknown;
74  }
75  default:
76  return SliceType::Unknown;
77  }
78 }
79 
80 bool scodeEq(buf& bs, uint pos, buf code) {
81  if(bs.size() - pos > code.size()) {
82  for(uint i = 0; i < code.size(); ++i) {
83  if(bs[pos + i] != code[i]) return false;
84  }
85  return true;
86  } else
87  return false;
88 }
89 
90 uint findStart(buf& bs, uint pos) {
91  buf codeLong = {0, 0, 0, 1};
92  buf codeShort = {0, 0, 1};
93  uint size = bs.size();
94  for(uint i = pos; i < size; ++i) {
95  if(bs[i] == 0) {
96  if(scodeEq(bs, i, codeLong)) {
97  return i + 4;
98  } else if(scodeEq(bs, i, codeShort)) {
99  return i + 3;
100  }
101  }
102  }
103  return size;
104 }
105 
106 uint findEnd(buf& bs, uint pos) {
107  buf end1 = {0, 0, 0};
108  buf end2 = {0, 0, 1};
109  uint size = bs.size();
110  for(uint i = pos; i < size; ++i) {
111  if(bs[i] == 0) {
112  if(scodeEq(bs, i, end1) || scodeEq(bs, i, end2)) {
113  return i;
114  }
115  }
116  }
117  return size;
118 }
119 
120 uint readUint(buf& bs, ulong start, ulong end) {
121  uint ret = 0;
122  for(ulong i = start; i < end; ++i) {
123  uint bit = (bs[(uint)(i / 8)] & (1 << (7 - i % 8))) > 0;
124  ret += bit * (1 << (end - i - 1));
125  }
126  return ret;
127 }
128 
129 std::tuple<uint, ulong> readGE(buf& bs, ulong pos) {
130  uint count = 0;
131  ulong size = bs.size() * 8;
132  while(pos < size) {
133  std::uint8_t bit = bs[(uint)(pos / 8)] & (char)(1 << (7 - pos % 8));
134  if(bit == 0) {
135  ++count;
136  ++pos;
137  } else
138  break;
139  }
140  ++count;
141  ulong start = pos;
142  ulong end = pos + count;
143  if(end > size) exit(30);
144  return std::make_tuple(readUint(bs, start, end) - 1, end);
145 }
146 
147 template <typename T>
148 std::vector<SliceType> H26xParser<T>::getTypes(buf& buffer, bool breakOnFirst) {
149  T p;
150  return p.parseBytestream(buffer, breakOnFirst);
151 }
152 
153 template <typename T>
154 std::vector<SliceType> H26xParser<T>::parseBytestream(buf& bs, bool breakOnFirst) {
155  uint pos = 0;
156  uint size = bs.size();
157  std::vector<SliceType> ret;
158  while(pos < size) {
159  uint start = findStart(bs, pos);
160  uint end = findEnd(bs, start);
161  if(start >= end) break;
162  parseNal(bs, start, ret);
163  pos = end;
164  if(breakOnFirst && ret.size() > 0) break;
165  }
166  return ret;
167 }
168 
169 void H264Parser::parseNal(buf& bs, uint start, std::vector<SliceType>& out) {
170  uint pos = start;
171  uint nalUnitType = bs[pos++] & 31;
172  uint nalUnitHeaderBytes = 1;
173  if(nalUnitType == 14 || nalUnitType == 20 || nalUnitType == 21) {
174  uint avc3dExtensionFlag = 0;
175  if(nalUnitType == 21) avc3dExtensionFlag = readUint(bs, pos * 8, pos * 8 + 1);
176  if(avc3dExtensionFlag)
177  nalUnitHeaderBytes += 2;
178  else
179  nalUnitHeaderBytes += 3;
180  }
181  pos = start + nalUnitHeaderBytes;
182  if(nalUnitType == 1 || nalUnitType == 5) {
183  const auto bpos1 = std::get<1>(readGE(bs, pos * 8));
184  uint tyNum;
185  ulong bpos2;
186  std::tie(tyNum, bpos2) = readGE(bs, bpos1);
187  pos = (uint)(bpos2 / 8) + (bpos2 % 8 > 0);
188  out.push_back(getSliceType(tyNum, Profile::H264));
189  }
190 }
191 
192 void H265Parser::parseNal(buf& bs, uint start, std::vector<SliceType>& out) {
193  nalUnitType = (bs[start] & 126) >> 1;
194  uint pos = start + 2;
195  if(nalUnitType == 33) {
196  // Sequence parameter set
197  uint spsMaxSubLayersMinus1 = (bs[pos] & 14) >> 1;
198  ++pos;
199  const auto bpos1 = std::get<1>(readGE(bs, pos * 8)); // We don't need this value
200  uint chr;
201  ulong bpos2;
202  std::tie(chr, bpos2) = readGE(bs, bpos1);
203  chromaFormatIdc = chr;
204  if(chromaFormatIdc) ++bpos2; // We don't need this value
205  uint pw;
206  ulong bpos3;
207  std::tie(pw, bpos3) = readGE(bs, bpos2);
208  uint ph;
209  ulong bpos4;
210  std::tie(ph, bpos4) = readGE(bs, bpos3);
213  uint conformanceWindowFlag = readUint(bs, bpos4, bpos4 + 1);
214  ulong bpos8 = ++bpos4;
215  if(conformanceWindowFlag) {
216  // We don't care about any of these values
217  auto bpos5 = std::get<1>(readGE(bs, bpos4));
218  auto bpos6 = std::get<1>(readGE(bs, bpos5));
219  auto bpos7 = std::get<1>(readGE(bs, bpos6));
220  auto tbpos8 = std::get<1>(readGE(bs, bpos7));
221  bpos8 = tbpos8;
222  }
223  auto bpos9 = std::get<1>(readGE(bs, bpos8));
224  auto bpos10 = std::get<1>(readGE(bs, bpos9));
225  auto bpos11 = std::get<1>(readGE(bs, bpos10));
226  uint spsSubLayerOrderingInfoPresentFlag = readUint(bs, bpos11, bpos11 + 1);
227  ulong bpos12 = ++bpos11;
228  for(uint i = spsSubLayerOrderingInfoPresentFlag ? 0 : spsMaxSubLayersMinus1; i <= spsMaxSubLayersMinus1; ++i) {
229  auto tbpos1 = std::get<1>(readGE(bs, bpos12));
230  auto tbpos2 = std::get<1>(readGE(bs, tbpos1));
231  auto tbpos3 = std::get<1>(readGE(bs, tbpos2));
232  bpos12 = tbpos3;
233  }
234  uint lm, ldm;
235  ulong bpos13, bpos14;
236  std::tie(lm, bpos13) = readGE(bs, bpos12);
237  std::tie(ldm, bpos14) = readGE(bs, bpos13);
240  pos = (uint)(bpos14 / 8) + (bpos14 % 8 > 0); // Update byte position with newest bit position
241  } else if(nalUnitType == 34) {
242  // Picture parameter set
243  auto bpos1 = std::get<1>(readGE(bs, pos * 8));
244  auto bpos2 = std::get<1>(readGE(bs, bpos1));
245  dependentSliceSegmentsEnabledFlag = readUint(bs, bpos2, bpos2 + 1);
246  bpos2 += 2;
247  numExtraSliceHeaderBits = readUint(bs, bpos2, bpos2 + 3);
248  bpos2 += 3;
249  pos = (uint)(bpos2 / 8) + (bpos2 % 8 > 0);
250  } else if(nalUnitType <= 9 || (16 <= nalUnitType && nalUnitType <= 21)) {
251  // Coded slice segment
252  ulong bpos1 = pos * 8;
253  uint firstSliceSegmentInPicFlag = readUint(bs, bpos1, bpos1 + 1);
254  ++bpos1;
255  if(16 <= nalUnitType && nalUnitType <= 23) ++bpos1;
256  auto bpos2 = std::get<1>(readGE(bs, bpos1));
257  uint dependentSliceSegmentFlag = 0;
258  if(!firstSliceSegmentInPicFlag) {
260  dependentSliceSegmentFlag = readUint(bs, bpos2, bpos2 + 1);
261  ++bpos2;
262  }
264  uint ctbSizeY = 1 << ctbLog2SizeY;
265  uint picWidthInCtbsY = ceil(picWidthInLumaSamples / ctbSizeY);
266  uint picHeightInCtbsY = ceil(picHeightInLumaSamples / ctbSizeY);
267  uint picSizeInCtbsY = picWidthInCtbsY * picHeightInCtbsY;
268  uint vlen = ceil(log2(picSizeInCtbsY));
269  bpos2 += vlen;
270  }
271  ulong bpos3 = bpos2;
272  if(!dependentSliceSegmentFlag) {
273  bpos2 += numExtraSliceHeaderBits;
274  uint tyNum;
275  ulong tbpos3;
276  std::tie(tyNum, tbpos3) = readGE(bs, bpos2);
277  bpos3 = tbpos3;
278  out.push_back(getSliceType(tyNum, Profile::H265));
279  }
280  pos = (uint)(bpos3 / 8) + (bpos3 % 8 > 0);
281  }
282 }
283 
284 std::vector<SliceType> getTypesH264(buf& bs, bool breakOnFirst) {
285  return H264Parser::getTypes(bs, breakOnFirst);
286 }
287 std::vector<SliceType> getTypesH265(buf& bs, bool breakOnFirst) {
288  return H265Parser::getTypes(bs, breakOnFirst);
289 }
290 
291 } // namespace utility
292 } // namespace dai
dai::utility::H265Parser::numExtraSliceHeaderBits
unsigned int numExtraSliceHeaderBits
Definition: H26xParsers.cpp:27
dai::utility::H265Parser::picHeightInLumaSamples
unsigned int picHeightInLumaSamples
Definition: H26xParsers.cpp:30
dai::utility::Profile::H264
@ H264
dai::utility::getTypesH265
std::vector< SliceType > getTypesH265(buf &bs, bool breakOnFirst)
Definition: H26xParsers.cpp:287
dai::utility::H264Parser
Definition: H26xParsers.cpp:20
dai::utility::H265Parser::nalUnitType
unsigned int nalUnitType
Definition: H26xParsers.cpp:25
dai::utility::SliceType::Unknown
@ Unknown
dai::utility::H264Parser::parseNal
void parseNal(const std::vector< std::uint8_t > &bs, unsigned int start, std::vector< SliceType > &out)
Definition: H26xParsers.cpp:169
dai::utility::uint
unsigned int uint
Definition: H26xParsers.cpp:38
dai::utility::readGE
std::tuple< uint, ulong > readGE(buf &bs, ulong pos)
Definition: H26xParsers.cpp:129
dai::utility::H265Parser::log2MinLumaCodingBlockSizeMinus3
unsigned int log2MinLumaCodingBlockSizeMinus3
Definition: H26xParsers.cpp:33
dai::utility::H265Parser::dependentSliceSegmentsEnabledFlag
unsigned int dependentSliceSegmentsEnabledFlag
Definition: H26xParsers.cpp:26
dai::utility::H265Parser::chromaFormatIdc
unsigned int chromaFormatIdc
Definition: H26xParsers.cpp:31
dai::utility::H265Parser::picWidthInLumaSamples
unsigned int picWidthInLumaSamples
Definition: H26xParsers.cpp:29
nanorpc::core::type::buffer
std::vector< std::uint8_t > buffer
Definition: type.h:28
dai::utility::scodeEq
bool scodeEq(buf &bs, uint pos, buf code)
Definition: H26xParsers.cpp:80
dai::utility::Profile
Profile
Definition: H26xParsers.hpp:9
dai::utility::SliceType::P
@ P
dai::utility::H265Parser
Definition: H26xParsers.cpp:24
DAI_SPAN_NAMESPACE_NAME::detail::size
constexpr auto size(const C &c) -> decltype(c.size())
Definition: span.hpp:167
dai::utility::SliceType::B
@ B
dai::utility::findEnd
uint findEnd(buf &bs, uint pos)
Definition: H26xParsers.cpp:106
dai::utility::readUint
uint readUint(buf &bs, ulong start, ulong end)
Definition: H26xParsers.cpp:120
dai::utility::Profile::H265
@ H265
dai::utility::findStart
uint findStart(buf &bs, uint pos)
Definition: H26xParsers.cpp:90
dai::utility::SliceType::SP
@ SP
dai::utility::SliceType::I
@ I
dai::utility::ulong
unsigned long ulong
Definition: H26xParsers.cpp:39
dai::utility::getTypesH264
std::vector< SliceType > getTypesH264(buf &bs, bool breakOnFirst)
Definition: H26xParsers.cpp:284
H26xParsers.hpp
dai::utility::SliceType
SliceType
Definition: H26xParsers.hpp:10
dai::utility::H26xParser
Definition: H26xParsers.cpp:10
dai::utility::H26xParser::parseNal
virtual void parseNal(const std::vector< std::uint8_t > &bs, unsigned int start, std::vector< SliceType > &out)=0
dai::utility::H26xParser::parseBytestream
std::vector< SliceType > parseBytestream(const std::vector< std::uint8_t > &bs, bool breakOnFirst)
Definition: H26xParsers.cpp:154
dai::utility::SliceType::SI
@ SI
dai::utility::getSliceType
SliceType getSliceType(uint num, Profile p)
Definition: H26xParsers.cpp:42
dai::utility::H265Parser::parseNal
void parseNal(const std::vector< std::uint8_t > &bs, unsigned int start, std::vector< SliceType > &out)
Definition: H26xParsers.cpp:192
dai
Definition: CameraExposureOffset.hpp:6
dai::utility::H26xParser::getTypes
static std::vector< SliceType > getTypes(const std::vector< std::uint8_t > &bs, bool breakOnFirst)
Definition: H26xParsers.cpp:148
dai::utility::H26xParser::~H26xParser
virtual ~H26xParser()=default
dai::utility::H265Parser::log2DiffMaxMinLumaCodingBlockSize
unsigned int log2DiffMaxMinLumaCodingBlockSize
Definition: H26xParsers.cpp:32
dai::utility::buf
const typedef std::vector< std::uint8_t > buf
Definition: H26xParsers.cpp:40


depthai
Author(s): Martin Peterlin
autogenerated on Sat Mar 22 2025 02:58:19