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