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