46 lines
1.8 KiB
C++
46 lines
1.8 KiB
C++
#pragma once
|
|
#include <QDataStream>
|
|
#include <QLocalSocket>
|
|
#include <QByteArray>
|
|
#include <functional>
|
|
|
|
namespace CallCameraProtocol {
|
|
enum Type : quint8 { Configure = 1, Quit, Ack, Devices, Frame, Stage, Error, Buffer };
|
|
constexpr quint32 FrameBytes = 1280 * 720 * 4;
|
|
constexpr quint32 MaxPacket = 65536;
|
|
|
|
// Только команды и метаданные. Пиксели — в mapping с владением Frame -> Ack, без shared mutex.
|
|
inline QByteArray packet(Type type, quint64 generation, const std::function<void(QDataStream&)>& write = {}) {
|
|
QByteArray result;
|
|
QDataStream out(&result, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_5_15);
|
|
out << quint32(0) << quint8(type) << generation;
|
|
if (write) write(out);
|
|
out.device()->seek(0); out << quint32(result.size() - 4);
|
|
return result;
|
|
}
|
|
|
|
class Reader {
|
|
QByteArray pending;
|
|
quint32 length = 0;
|
|
public:
|
|
bool read(QLocalSocket& socket, const std::function<bool(quint8, quint64, QDataStream&)>& consume) {
|
|
while (socket.bytesAvailable()) {
|
|
const qsizetype wanted = length ? length : 4;
|
|
pending += socket.read(wanted - pending.size());
|
|
if (pending.size() != wanted) return true;
|
|
QDataStream in(pending); in.setVersion(QDataStream::Qt_5_15);
|
|
if (!length) {
|
|
in >> length; pending.clear();
|
|
if (length < 9 || length > MaxPacket) return false;
|
|
} else {
|
|
quint8 type; quint64 generation; in >> type >> generation;
|
|
bool valid = consume(type, generation, in) && in.status() == QDataStream::Ok && in.atEnd();
|
|
pending.clear(); length = 0;
|
|
if (!valid) return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
}
|