Files
utun2/tools/chatgui/src/call_camera_protocol.h
T

52 lines
2.1 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 = 1920 * 1080 * 4;
constexpr quint32 MaxPacket = 65536;
// Full HD в обеих ориентациях; чётные размеры необходимы для YUV420.
inline bool validSize(int width, int height) {
return width >= 16 && height >= 16 && width <= 1920 && height <= 1920
&& (width <= 1080 || height <= 1080) && !(width % 2) && !(height % 2);
}
// Только команды и метаданные. Пиксели — в 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;
}
};
}