Tag Parser  8.2.0
C++ library for reading and writing MP4 (iTunes), ID3, Vorbis, Opus, FLAC and Matroska tags
oggpage.cpp
Go to the documentation of this file.
1 #include "./oggpage.h"
2 
3 #include "../exceptions.h"
4 
5 #include <c++utilities/conversion/binaryconversion.h>
6 #include <c++utilities/io/binaryreader.h>
7 
8 using namespace std;
9 using namespace IoUtilities;
10 using namespace ConversionUtilities;
11 
12 namespace TagParser {
13 
25 void OggPage::parseHeader(istream &stream, uint64 startOffset, int32 maxSize)
26 {
27  // prepare reading
28  stream.seekg(static_cast<streamoff>(startOffset));
29  BinaryReader reader(&stream);
30  if (maxSize < 27) {
31  throw TruncatedDataException();
32  } else {
33  maxSize -= 27;
34  }
35  // read header values
36  if (reader.readUInt32LE() != 0x5367674f) {
37  throw InvalidDataException();
38  }
39  m_startOffset = startOffset;
40  m_streamStructureVersion = reader.readByte();
41  m_headerTypeFlag = reader.readByte();
42  m_absoluteGranulePosition = reader.readUInt64LE();
43  m_streamSerialNumber = reader.readUInt32LE();
44  m_sequenceNumber = reader.readUInt32LE();
45  m_checksum = reader.readUInt32LE();
46  m_segmentCount = reader.readByte();
47  m_segmentSizes.clear();
48  if (m_segmentCount > 0) {
49  if (maxSize < m_segmentCount) {
50  throw TruncatedDataException();
51  } else {
52  maxSize -= m_segmentCount;
53  }
54  // read segment size tabe
55  m_segmentSizes.push_back(0);
56  for (byte i = 0; i < m_segmentCount;) {
57  byte entry = reader.readByte();
58  maxSize -= entry;
59  m_segmentSizes.back() += entry;
60  if (++i < m_segmentCount && entry < 0xff) {
61  m_segmentSizes.push_back(0);
62  }
63  }
64  // check whether the maximum size is exceeded
65  if (maxSize < 0) {
66  throw TruncatedDataException();
67  }
68  }
69 }
70 
75 uint32 OggPage::computeChecksum(istream &stream, uint64 startOffset)
76 {
77  stream.seekg(static_cast<streamoff>(startOffset));
78  uint32 crc = 0x0;
79  byte value, segmentTableSize = 0, segmentTableIndex = 0;
80  for (uint32 i = 0, segmentLength = 27; i != segmentLength; ++i) {
81  switch (i) {
82  case 22:
83  // bytes 22, 23, 24, 25 hold denoted checksum and must be set to zero
84  stream.seekg(4, ios_base::cur);
85  FALLTHROUGH;
86  case 23:
87  case 24:
88  case 25:
89  value = 0;
90  break;
91  case 26:
92  // byte 26 holds the number of segment sizes
93  segmentLength += (segmentTableSize = (value = static_cast<byte>(stream.get())));
94  break;
95  default:
96  value = static_cast<byte>(stream.get());
97  if (i > 26 && segmentTableIndex < segmentTableSize) {
98  // bytes 27 to (27 + segment size count) hold page size
99  segmentLength += value;
100  ++segmentTableIndex;
101  }
102  }
103  crc = (crc << 8) ^ BinaryReader::crc32Table[((crc >> 24) & 0xFF) ^ value];
104  }
105  return crc;
106 }
107 
112 void OggPage::updateChecksum(iostream &stream, uint64 startOffset)
113 {
114  char buff[4];
115  LE::getBytes(computeChecksum(stream, startOffset), buff);
116  stream.seekp(static_cast<streamoff>(startOffset + 22));
117  stream.write(buff, sizeof(buff));
118 }
119 
124 uint32 OggPage::makeSegmentSizeDenotation(ostream &stream, uint32 size)
125 {
126  uint32 bytesWritten = 1;
127  while (size >= 0xff) {
128  stream.put(static_cast<char>(0xff));
129  size -= 0xff;
130  ++bytesWritten;
131  }
132  stream.put(static_cast<char>(size));
133  return bytesWritten;
134 }
135 
136 } // namespace TagParser
The exception that is thrown when the data to be parsed is truncated and therefore can not be parsed ...
Definition: exceptions.h:39
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:25
Contains all classes and functions of the TagInfo library.
Definition: aaccodebook.h:9