Tag Parser  8.0.1
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:32
STL namespace.
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