Files
Renderive/web_server/app/common/Pixel_Frame.cpp
2026-08-15 21:48:23 +08:00

49 lines
2.0 KiB
C++

#include "Pixel_Frame.h"
#include <cstring>
#include <limits>
namespace renderive::web {
namespace {
void write_u32_le(char* target, std::uint32_t value) {
target[0] = static_cast<char>(value & 0xffU);
target[1] = static_cast<char>((value >> 8U) & 0xffU);
target[2] = static_cast<char>((value >> 16U) & 0xffU);
target[3] = static_cast<char>((value >> 24U) & 0xffU);
}
void write_u64_le(char* target, std::uint64_t value) {
write_u32_le(target, static_cast<std::uint32_t>(value));
write_u32_le(target + 4, static_cast<std::uint32_t>(value >> 32U));
}
}
std::string make_rgba8_pixel_frame(std::uint32_t width, std::uint32_t height, std::uint64_t sequence) {
if (width == 0 || height == 0)
return {};
const std::size_t row_size = static_cast<std::size_t>(width) * 4U;
if (static_cast<std::size_t>(height) > (std::numeric_limits<std::size_t>::max() - pixel_frame_header_size) / row_size)
return {};
std::string frame(pixel_frame_header_size + row_size * height, '\0');
frame[0] = 'R';
frame[1] = 'V';
frame[2] = 'P';
frame[3] = '2';
write_u32_le(frame.data() + 4, width);
write_u32_le(frame.data() + 8, height);
write_u32_le(frame.data() + 12, static_cast<std::uint32_t>(row_size));
write_u64_le(frame.data() + 16, sequence);
return frame;
}
std::string encode_rgba8_pixel_frame(const std::byte* data, std::uint32_t width, std::uint32_t height, std::uint32_t stride, std::uint64_t sequence) {
if (data == nullptr || stride < width * 4U)
return {};
std::string frame = make_rgba8_pixel_frame(width, height, sequence);
if (frame.empty())
return {};
const std::size_t row_size = static_cast<std::size_t>(width) * 4U;
char* output = frame.data() + pixel_frame_header_size;
for (std::uint32_t y = 0; y < height; ++y) {
const auto* row = data + static_cast<std::size_t>(y) * stride;
std::memcpy(output + static_cast<std::size_t>(y) * row_size, row, row_size);
}
return frame;
}
}