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