2015-09-06 19:57:33 +02:00
|
|
|
#include "./avcconfiguration.h"
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2018-08-23 23:19:44 +02:00
|
|
|
#include "../diagnostics.h"
|
2016-02-17 20:19:05 +01:00
|
|
|
#include "../exceptions.h"
|
|
|
|
#include "../mediaformat.h"
|
|
|
|
|
|
|
|
#include <c++utilities/io/binaryreader.h>
|
|
|
|
|
2018-06-02 22:56:08 +02:00
|
|
|
#include <limits>
|
|
|
|
|
2016-02-17 20:19:05 +01:00
|
|
|
using namespace std;
|
2019-06-10 22:49:11 +02:00
|
|
|
using namespace CppUtilities;
|
2016-02-17 20:19:05 +01:00
|
|
|
|
2018-03-06 23:09:15 +01:00
|
|
|
namespace TagParser {
|
2015-04-22 19:22:01 +02:00
|
|
|
|
2016-08-04 00:16:19 +02:00
|
|
|
/*!
|
|
|
|
* \class AvcConfiguration
|
|
|
|
* \brief The AvcConfiguration struct provides a parser for AVC configuration.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Parses the AVC configuration using the specified \a reader.
|
|
|
|
* \throws Throws TruncatedDataException() when the config size exceeds the specified \a maxSize.
|
|
|
|
*/
|
2019-03-13 19:06:42 +01:00
|
|
|
void AvcConfiguration::parse(BinaryReader &reader, std::uint64_t maxSize, Diagnostics &diag)
|
2016-02-17 20:19:05 +01:00
|
|
|
{
|
2018-03-07 01:17:50 +01:00
|
|
|
if (maxSize < 7) {
|
2016-02-17 20:19:05 +01:00
|
|
|
throw TruncatedDataException();
|
|
|
|
}
|
|
|
|
maxSize -= 7;
|
|
|
|
|
|
|
|
reader.stream()->seekg(1, ios_base::cur); // always 1
|
|
|
|
profileIndication = reader.readByte();
|
|
|
|
profileCompat = reader.readByte();
|
|
|
|
levelIndication = reader.readByte();
|
|
|
|
naluSizeLength = (reader.readByte() & 0x03) + 1;
|
|
|
|
|
|
|
|
// read SPS info entries
|
2020-12-01 01:44:51 +01:00
|
|
|
std::uint8_t spsEntryCount = reader.readByte() & 0x0f;
|
|
|
|
std::uint8_t ignoredSpsEntries = 0;
|
|
|
|
spsInfos.reserve(spsEntryCount);
|
|
|
|
for (; spsEntryCount; --spsEntryCount) {
|
2020-12-01 01:12:46 +01:00
|
|
|
if (maxSize < SpsInfo::minSize) {
|
2016-02-17 20:19:05 +01:00
|
|
|
throw TruncatedDataException();
|
|
|
|
}
|
2020-12-01 01:44:51 +01:00
|
|
|
auto error = false;
|
2016-02-17 20:19:05 +01:00
|
|
|
try {
|
2020-12-01 01:12:46 +01:00
|
|
|
spsInfos.emplace_back().parse(
|
2019-03-13 19:06:42 +01:00
|
|
|
reader, maxSize > numeric_limits<std::uint32_t>::max() ? numeric_limits<std::uint32_t>::max() : static_cast<std::uint32_t>(maxSize));
|
2018-03-07 01:17:50 +01:00
|
|
|
} catch (const TruncatedDataException &) {
|
2020-12-01 01:12:46 +01:00
|
|
|
if (spsInfos.back().size > (maxSize - SpsInfo::minSize)) {
|
|
|
|
throw; // sps info looks bigger than bytes to read
|
2016-02-17 20:19:05 +01:00
|
|
|
}
|
2020-12-01 01:44:51 +01:00
|
|
|
error = true; // sps info exceeds denoted size
|
2018-03-07 01:17:50 +01:00
|
|
|
} catch (const Failure &) {
|
2020-12-01 01:44:51 +01:00
|
|
|
error = true;
|
2016-02-17 20:19:05 +01:00
|
|
|
}
|
|
|
|
maxSize -= spsInfos.back().size;
|
2020-12-01 01:44:51 +01:00
|
|
|
if (error) {
|
|
|
|
spsInfos.pop_back();
|
|
|
|
++ignoredSpsEntries;
|
|
|
|
}
|
2016-02-17 20:19:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// read PPS info entries
|
2020-12-01 01:44:51 +01:00
|
|
|
std::uint8_t ppsEntryCount = reader.readByte();
|
|
|
|
std::uint8_t ignoredPpsEntries = 0;
|
|
|
|
ppsInfos.reserve(ppsEntryCount);
|
|
|
|
for (; ppsEntryCount; --ppsEntryCount) {
|
2020-12-01 01:12:46 +01:00
|
|
|
if (maxSize < PpsInfo::minSize) {
|
2016-02-17 20:19:05 +01:00
|
|
|
throw TruncatedDataException();
|
|
|
|
}
|
2020-12-01 01:44:51 +01:00
|
|
|
auto error = false;
|
2016-02-17 20:19:05 +01:00
|
|
|
try {
|
2020-12-01 01:12:46 +01:00
|
|
|
ppsInfos.emplace_back().parse(
|
2019-03-13 19:06:42 +01:00
|
|
|
reader, maxSize > numeric_limits<std::uint32_t>::max() ? numeric_limits<std::uint32_t>::max() : static_cast<std::uint32_t>(maxSize));
|
2018-03-07 01:17:50 +01:00
|
|
|
} catch (const TruncatedDataException &) {
|
2020-12-01 01:12:46 +01:00
|
|
|
if (ppsInfos.back().size > (maxSize - PpsInfo::minSize)) {
|
|
|
|
throw; // pps info looks bigger than bytes to read
|
2016-02-17 20:19:05 +01:00
|
|
|
}
|
2020-12-01 01:44:51 +01:00
|
|
|
error = true; // pps info exceeds denoted size
|
2018-03-07 01:17:50 +01:00
|
|
|
} catch (const Failure &) {
|
2020-12-01 01:44:51 +01:00
|
|
|
error = true;
|
2016-02-17 20:19:05 +01:00
|
|
|
}
|
|
|
|
maxSize -= ppsInfos.back().size;
|
2020-12-01 01:44:51 +01:00
|
|
|
if (error) {
|
|
|
|
ppsInfos.pop_back();
|
|
|
|
++ignoredPpsEntries;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// log parsing errors
|
|
|
|
if (ignoredSpsEntries || ignoredPpsEntries) {
|
|
|
|
diag.emplace_back(DiagLevel::Debug,
|
|
|
|
argsToString(
|
|
|
|
"Ignored ", ignoredSpsEntries, " SPS entries and ", ignoredPpsEntries, " PPS entries. This AVC config is likely just not supported."),
|
|
|
|
"parsing AVC config");
|
2016-02-17 20:19:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ignore remaining data
|
|
|
|
}
|
|
|
|
|
2018-03-07 01:17:50 +01:00
|
|
|
} // namespace TagParser
|