5#include <QtCore/QByteArrayView>
13 qCDebug(RTCMFrameDecoderLog) <<
this;
18 qCDebug(RTCMFrameDecoderLog) <<
this;
23 const uint16_t validatedFrameSize = _frameSize ? _discardCandidate() : 0;
27 _bytes[_size++] = byte;
28 return _inspect(validatedFrameSize);
36 return _inspect(_discardCandidate());
39void RTCMFramer::_discardPrefix(uint16_t count)
42 std::move(_bytes.begin() + count, _bytes.begin() + _size, _bytes.begin());
44 _recoverySize -= (std::min) (_recoverySize, count);
48uint16_t RTCMFramer::_discardCandidate()
50 uint16_t validatedFrameSize = 0;
51 uint16_t searchOffset = _frameSize;
53 _recoverySize = (std::max) (_recoverySize, _frameSize);
56 uint16_t discardSize = _frameSize;
57 if (searchOffset < _recoverySize) {
58 discardSize = _recoverySize;
60 const std::span<const uint8_t> bytes{_bytes.data(), _recoverySize};
61 for (uint16_t offset = searchOffset; offset < _recoverySize; ++offset) {
62 const auto suffix = bytes.subspan(offset);
63 if (suffix[0] !=
PREAMBLE || (suffix.size() >= 2 && (suffix[1] & 0xfc))) {
67 discardSize = (std::min) (discardSize, offset);
70 const size_t payloadSize = ((suffix[1] & 3) << 8) | suffix[2];
71 if (payloadSize < 2) {
75 if (length > suffix.size()) {
76 discardSize = (std::min) (discardSize, offset);
81 validatedFrameSize =
static_cast<uint16_t
>(length);
86 _discardPrefix(discardSize);
89 return validatedFrameSize;
92bool RTCMFramer::_inspect(uint16_t validatedFrameSize)
97 const auto preamble = std::find(_bytes.begin(), _bytes.begin() + _size,
PREAMBLE);
98 _discardPrefix(
static_cast<uint16_t
>(preamble - _bytes.begin()));
99 if (_size >= 2 && (_bytes[1] & 0xfc)) {
106 _payloadSize = ((_bytes[1] & 3) << 8) | _bytes[2];
107 if (_payloadSize < 2) {
112 if (_size < expectedSize) {
115 _frameSize = expectedSize;
122 _receiptTimes[_nextReceiptIndex] = receivedAtMs;
123 _nextReceiptIndex = (_nextReceiptIndex + 1) % _receiptTimes.size();
140 const auto frame = _framer.
frame();
141 const size_t firstReceiptIndex =
142 (_nextReceiptIndex + _receiptTimes.size() - _framer.
bufferedSize()) % _receiptTimes.size();
144 result.valid = _framer.
valid();
145 result.filtered = result.valid && !_whitelist.isEmpty() && !_whitelist.contains(result.messageId);
152 _nextReceiptIndex = 0;
#define QGC_LOGGING_CATEGORY(name, categoryStr)
Frames RTCM bytes while retaining the first fragment's monotonic receipt time.
std::optional< RTCMDecodedFrame > nextFrame()
Drain after addByte() returns a result, before feeding more bytes.
std::optional< RTCMDecodedFrame > addByte(uint8_t byte, qint64 receivedAtMs)
static constexpr uint16_t CRC_SIZE
uint16_t messageId() const
std::span< const uint8_t > frame() const
Complete candidate, including malformed headers; empty while incomplete.
uint16_t bufferedSize() const
Retained suffix length, including bytes beyond the current candidate.
static constexpr uint16_t HEADER_SIZE
static constexpr uint8_t PREAMBLE
static bool isValidFrame(std::span< const uint8_t > bytes)
bool addByte(uint8_t byte)