Tag Parser  9.2.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
avcinfo.cpp
Go to the documentation of this file.
1 #include "./avcinfo.h"
2 
3 #include "../exceptions.h"
4 
5 #include <c++utilities/io/binaryreader.h>
6 #include <c++utilities/io/bitreader.h>
7 
8 #include <memory>
9 #include <unordered_map>
10 
11 using namespace std;
12 using namespace CppUtilities;
13 
14 namespace TagParser {
15 
24 void SpsInfo::parse(BinaryReader &reader, std::uint32_t maxSize)
25 {
26  // read (and check) size
27  if (maxSize < 2) {
28  throw TruncatedDataException();
29  }
30  maxSize -= 2;
31  if ((size = reader.readUInt16BE()) > maxSize) {
32  throw TruncatedDataException();
33  }
34 
35  // buffer data for reading with BitReader
36  auto buffer = make_unique<char[]>(size);
37  reader.read(buffer.get(), size);
38  BitReader bitReader(buffer.get(), size);
39 
40  try {
41  // read general values
42  bitReader.skipBits(3);
43  if (bitReader.readBits<std::uint8_t>(5) != 7) {
44  throw InvalidDataException();
45  }
46  profileIndication = bitReader.readBits<std::uint8_t>(8);
47  profileConstraints = bitReader.readBits<std::uint8_t>(8);
48  levelIndication = bitReader.readBits<std::uint8_t>(8);
49  id = bitReader.readUnsignedExpGolombCodedBits<ugolomb>();
50 
51  // read chroma profile specific values
52  switch (profileIndication) {
53  case 44:
54  case 83:
55  case 86:
56  case 100:
57  case 110:
58  case 118:
59  case 122:
60  case 128:
61  case 244:
62  // high-level profile
63  if ((chromaFormatIndication = bitReader.readUnsignedExpGolombCodedBits<ugolomb>()) == 3) {
64  bitReader.skipBits(1); // separate color plane flag
65  }
66  bitReader.readUnsignedExpGolombCodedBits<std::uint8_t>(); // bit depth luma minus8
67  bitReader.readUnsignedExpGolombCodedBits<std::uint8_t>(); // bit depth chroma minus8
68  bitReader.skipBits(1); // qpprime y zero transform bypass flag
69  if (bitReader.readBit()) { // sequence scaling matrix present flag
70  for (std::uint8_t i = 0; i < 8; ++i) {
71  // TODO: store values
72  if (bitReader.readBit()) { // sequence scaling list present
73  if (i < 6) {
74  bitReader.skipBits(16); // scalingList4x4[i]
75  } else {
76  bitReader.skipBits(64); // scalingList8x8[i - 6]
77  }
78  }
79  }
80  }
81  break;
82  default:
83  chromaFormatIndication = 1; // assume YUV 4:2:0
84  }
85 
86  // read misc values
87  log2MaxFrameNum = bitReader.readUnsignedExpGolombCodedBits<ugolomb>() + 4;
88  switch (pictureOrderCountType = bitReader.readUnsignedExpGolombCodedBits<ugolomb>()) {
89  case 0:
90  log2MaxPictureOrderCountLsb = bitReader.readUnsignedExpGolombCodedBits<ugolomb>() + 4;
91  break;
92  case 1:
93  deltaPicOrderAlwaysZeroFlag = bitReader.readBit();
94  offsetForNonRefPic = bitReader.readSignedExpGolombCodedBits<sgolomb>();
95  offsetForTopToBottomField = bitReader.readSignedExpGolombCodedBits<sgolomb>();
96  numRefFramesInPicOrderCntCycle = bitReader.readUnsignedExpGolombCodedBits<ugolomb>();
97  for (std::uint8_t i = 0; i < numRefFramesInPicOrderCntCycle; ++i) {
98  bitReader.readUnsignedExpGolombCodedBits<ugolomb>(); // offset for ref frames
99  }
100  break;
101  case 2:
102  break;
103  default:
104  throw InvalidDataException();
105  }
106  bitReader.readUnsignedExpGolombCodedBits<ugolomb>(); // ref frames num
107  bitReader.skipBits(1); // gaps in frame num value allowed flag
108 
109  // read picture size related values
110  Size mbSize;
111  mbSize.setWidth(bitReader.readUnsignedExpGolombCodedBits<std::uint32_t>() + 1);
112  mbSize.setHeight(bitReader.readUnsignedExpGolombCodedBits<std::uint32_t>() + 1);
113  if (!(frameMbsOnly = bitReader.readBit())) { // frame mbs only flag
114  bitReader.readBit(); // mb adaptive frame field flag
115  }
116  bitReader.skipBits(1); // distinct 8x8 inference flag
117 
118  // read cropping values
119  if (bitReader.readBit()) { // frame cropping flag
120  cropping.setLeft(bitReader.readUnsignedExpGolombCodedBits<std::uint32_t>());
121  cropping.setRight(bitReader.readUnsignedExpGolombCodedBits<std::uint32_t>());
122  cropping.setTop(bitReader.readUnsignedExpGolombCodedBits<std::uint32_t>());
123  cropping.setBottom(bitReader.readUnsignedExpGolombCodedBits<std::uint32_t>());
124  }
125 
126  // calculate actual picture size
127  if (!cropping.isNull()) {
128  // determine cropping scale
129  ugolomb croppingScaleX, croppingScaleY;
130  switch (chromaFormatIndication) {
131  case 1: // 4:2:0
132  croppingScaleX = 2;
133  croppingScaleY = frameMbsOnly ? 2 : 4;
134  break;
135  case 2: // 4:2:2
136  croppingScaleX = 2;
137  croppingScaleY = 2 - frameMbsOnly;
138  break;
139  default: // case 0: monochrome, case 3: 4:4:4
140  croppingScaleX = 1;
141  croppingScaleY = 2 - frameMbsOnly;
142  break;
143  }
144  pictureSize.setWidth(mbSize.width() * 16 - croppingScaleX * (cropping.left() + cropping.right()));
145  pictureSize.setHeight((2 - frameMbsOnly) * mbSize.height() * 16 - croppingScaleY * (cropping.top() + cropping.bottom()));
146  } else {
147  pictureSize.setWidth(mbSize.width() * 16);
148  pictureSize.setHeight((2 - frameMbsOnly) * mbSize.height() * 16);
149  }
150 
151  // read VUI (video usability information)
152  if ((vuiPresent = bitReader.readBit())) {
153  if ((bitReader.readBit())) { // PAR present flag
154  pixelAspectRatio = AspectRatio(bitReader.readBits<std::uint8_t>(8));
155  if (pixelAspectRatio.isExtended()) {
156  // read extended SAR
157  pixelAspectRatio.numerator = bitReader.readBits<std::uint16_t>(16);
158  pixelAspectRatio.denominator = bitReader.readBits<std::uint16_t>(16);
159  }
160  }
161 
162  // read/skip misc values
163  if (bitReader.readBit()) { // overscan info present
164  bitReader.skipBits(1); // overscan appropriate
165  }
166  if (bitReader.readBit()) { // video signal type present
167  bitReader.skipBits(4); // video format and video full range
168  if (bitReader.readBit()) { // color description present
169  bitReader.skipBits(24); // color primaries, transfer characteristics, matrix coefficients
170  }
171  }
172  if (bitReader.readBit()) { // chroma loc info present
173  bitReader.readUnsignedExpGolombCodedBits<std::uint8_t>(); // chroma sample loc type top field
174  bitReader.readUnsignedExpGolombCodedBits<std::uint8_t>(); // chroma sample loc type bottom field
175  }
176 
177  // read timing info
178  if ((timingInfo.isPresent = bitReader.readBit())) {
179  timingInfo.unitsInTick = bitReader.readBits<std::uint32_t>(32);
180  timingInfo.timeScale = bitReader.readBits<std::uint32_t>(32);
181  timingInfo.fixedFrameRate = bitReader.readBit();
182  }
183 
184  // skip hrd parameters
185  hrdParametersPresent = 0;
186  if (bitReader.readBit()) { // nal hrd parameters present
187  nalHrdParameters.parse(bitReader);
188  hrdParametersPresent = 1;
189  }
190  if (bitReader.readBit()) { // vcl hrd parameters present
191  vclHrdParameters.parse(bitReader);
192  hrdParametersPresent = 1;
193  }
194  if (hrdParametersPresent) {
195  bitReader.skipBits(1); // low delay hrd flag
196  }
197 
198  pictureStructPresent = bitReader.readBit();
199 
200  // TODO: investigate error (truncated data) when parsing mtx-test-data/mkv/attachment-without-fileuid.mkv
201  if (bitReader.readBit()) { // bitstream restriction flag
202  bitReader.skipBits(1); // motion vectors over pic boundries flag
203  bitReader.readUnsignedExpGolombCodedBits<std::uint8_t>(); // max bytes per pic denom
204  bitReader.readUnsignedExpGolombCodedBits<std::uint8_t>(); // max bytes per mb denom
205  bitReader.readUnsignedExpGolombCodedBits<std::uint8_t>(); // log2 max mv length horizontal
206  bitReader.readUnsignedExpGolombCodedBits<std::uint8_t>(); // log2 max mv length vertical
207  bitReader.readUnsignedExpGolombCodedBits<std::uint8_t>(); // reorder frames num
208  bitReader.readUnsignedExpGolombCodedBits<std::uint8_t>(); // max decoder frame buffering
209  }
210  }
211 
212  } catch (const std::ios_base::failure &) {
213  throw TruncatedDataException();
214  }
215 }
216 
225 void PpsInfo::parse(BinaryReader &reader, std::uint32_t maxSize)
226 {
227  // read (and check) size
228  if (maxSize < 2) {
229  throw TruncatedDataException();
230  }
231  maxSize -= 2;
232  if ((size = reader.readUInt16BE()) > maxSize) {
233  throw TruncatedDataException();
234  }
235 
236  // buffer data for reading with BitReader
237  auto buffer = make_unique<char[]>(size);
238  reader.read(buffer.get(), size);
239  BitReader bitReader(buffer.get(), size);
240 
241  try {
242  // read general values
243  bitReader.skipBits(1); // zero bit
244  if (bitReader.readBits<std::uint8_t>(5) != 8) { // nal unit type
245  throw InvalidDataException();
246  }
247  id = bitReader.readUnsignedExpGolombCodedBits<ugolomb>();
248  spsId = bitReader.readUnsignedExpGolombCodedBits<ugolomb>();
249  bitReader.skipBits(1); // entropy coding mode flag
250  picOrderPresent = bitReader.readBit();
251  } catch (const std::ios_base::failure &) {
252  throw TruncatedDataException();
253  }
254 }
255 
265 void HrdParameters::parse(CppUtilities::BitReader &reader)
266 {
267  cpbCount = reader.readUnsignedExpGolombCodedBits<ugolomb>() + 1;
268  bitRateScale = reader.readBits<std::uint8_t>(4);
269  cpbSizeScale = reader.readBits<std::uint8_t>(4);
270  for (ugolomb i = 0; i < cpbCount; ++i) {
271  // just skip those values
272  reader.readUnsignedExpGolombCodedBits<std::uint8_t>(); // bit rate value minus 1
273  reader.readUnsignedExpGolombCodedBits<std::uint8_t>(); // cpb size value minus 1
274  reader.skipBits(1); // cbr flag
275  }
276  initialCpbRemovalDelayLength = reader.readBits<std::uint8_t>(5) + 1;
277  cpbRemovalDelayLength = reader.readBits<std::uint8_t>(5) + 1;
278  cpbOutputDelayLength = reader.readBits<std::uint8_t>(5) + 1;
279  timeOffsetLength = reader.readBits<std::uint8_t>(5);
280 }
281 
299 } // namespace TagParser
TagParser
Contains all classes and functions of the TagInfo library.
Definition: aaccodebook.h:10
TagParser::ugolomb
std::uint32_t ugolomb
Type used to store unsigned integer values using golomb coding.
Definition: avcinfo.h:18
TagParser::Size::setWidth
void setWidth(std::uint32_t value)
Sets the width.
Definition: size.h:75
avcinfo.h
CppUtilities
Definition: abstractcontainer.h:15
TagParser::sgolomb
std::int32_t sgolomb
Type used to store signed integer values using golomb coding.
Definition: avcinfo.h:23
TagParser::Size
The Size class defines the size of a two-dimensional object using integer point precision.
Definition: size.h:16
TagParser::Size::setHeight
void setHeight(std::uint32_t value)
Sets the height.
Definition: size.h:83
TagParser::InvalidDataException
The exception that is thrown when the data to be parsed or to be made seems invalid and therefore can...
Definition: exceptions.h:25
TagParser::TruncatedDataException
The exception that is thrown when the data to be parsed is truncated and therefore can not be parsed ...
Definition: exceptions.h:39
TagParser::AspectRatio
The AspectRatio struct defines an aspect ratio.
Definition: aspectratio.h:13
TagParser::Size::height
constexpr std::uint32_t height() const
Returns the height.
Definition: size.h:67
TagParser::Size::width
constexpr std::uint32_t width() const
Returns the width.
Definition: size.h:59