mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-11-05 13:42:38 +08:00
[feat] integrate CrossDesk CLI with terminal rendering and npm packaging
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
#include "controller_session.h"
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
|
||||
namespace crossdesk {
|
||||
bool LatestFrame::Submit(const MiniRtcVideoFrame &f, uint64_t generation) {
|
||||
std::lock_guard lock(mutex_);
|
||||
if (generation != generation_)
|
||||
return false;
|
||||
const size_t w = f.width, h = f.height;
|
||||
if (!w || !h || (w & 1) || (h & 1) || w > 8192 || h > 8192 ||
|
||||
w * h > 16777216) {
|
||||
++invalid_;
|
||||
return false;
|
||||
}
|
||||
const size_t size = w * h * 3 / 2;
|
||||
const auto *n = f.native_frame;
|
||||
const bool native = n && n->struct_size >= sizeof(*n) && n->width == w &&
|
||||
n->height == h && n->owner;
|
||||
if (native && n->type == MiniRtcNativeVideoFrameCpuNv12) {
|
||||
const auto &p = n->payload.cpu_nv12;
|
||||
if (!p.y_plane || !p.uv_plane || p.y_stride < w || p.uv_stride < w ||
|
||||
p.y_stride > INT_MAX || p.uv_stride > INT_MAX) {
|
||||
++invalid_;
|
||||
return false;
|
||||
}
|
||||
spare_.resize(size);
|
||||
for (size_t y = 0; y < h; ++y)
|
||||
std::memcpy(spare_.data() + y * w, p.y_plane + y * p.y_stride, w);
|
||||
for (size_t y = 0; y < h / 2; ++y)
|
||||
std::memcpy(spare_.data() + w * h + y * w, p.uv_plane + y * p.uv_stride,
|
||||
w);
|
||||
} else if (f.data && f.size >= size) {
|
||||
spare_.resize(size);
|
||||
std::memcpy(spare_.data(), f.data, size);
|
||||
} else if (native && n->copy_to_nv12) {
|
||||
spare_.resize(size);
|
||||
if (n->copy_to_nv12(n->owner, spare_.data(), size) != 0) {
|
||||
++invalid_;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
++invalid_;
|
||||
return false;
|
||||
}
|
||||
DecodedFrame frame{f.width,
|
||||
f.height,
|
||||
generation,
|
||||
++received_,
|
||||
std::chrono::steady_clock::now(),
|
||||
std::move(spare_)};
|
||||
// Keep a valid pending frame until the replacement has been copied.
|
||||
if (pending_) {
|
||||
spare_.swap(pending_->nv12);
|
||||
++dropped_;
|
||||
}
|
||||
pending_ = std::move(frame);
|
||||
return true;
|
||||
}
|
||||
std::optional<DecodedFrame> LatestFrame::Take(DecodedFrame *recycle) {
|
||||
std::lock_guard lock(mutex_);
|
||||
if (!pending_)
|
||||
return {};
|
||||
auto result = std::move(pending_);
|
||||
pending_.reset();
|
||||
if (recycle && recycle->nv12.capacity() > spare_.capacity())
|
||||
spare_.swap(recycle->nv12);
|
||||
return result;
|
||||
}
|
||||
void LatestFrame::Reset(uint64_t generation) {
|
||||
std::lock_guard lock(mutex_);
|
||||
generation_ = generation;
|
||||
pending_.reset();
|
||||
spare_.clear();
|
||||
}
|
||||
nlohmann::json LatestFrame::Stats() const {
|
||||
std::lock_guard lock(mutex_);
|
||||
return {{"received", received_},
|
||||
{"replaced", dropped_},
|
||||
{"invalid", invalid_},
|
||||
{"pending", pending_ ? 1 : 0}};
|
||||
}
|
||||
nlohmann::json ParseBoundedJson(const std::string &text) {
|
||||
if (text.size() > 65536)
|
||||
return {};
|
||||
int depth = 0;
|
||||
bool quoted = false, escaped = false;
|
||||
for (char c : text) {
|
||||
if (quoted) {
|
||||
if (escaped)
|
||||
escaped = false;
|
||||
else if (c == '\\')
|
||||
escaped = true;
|
||||
else if (c == '"')
|
||||
quoted = false;
|
||||
} else if (c == '"')
|
||||
quoted = true;
|
||||
else if (c == '{' || c == '[') {
|
||||
if (++depth > 32)
|
||||
return {};
|
||||
} else if (c == '}' || c == ']') {
|
||||
if (--depth < 0)
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return nlohmann::json::parse(text, nullptr, false);
|
||||
}
|
||||
std::string SafeText(const std::string &text, size_t limit) {
|
||||
// ASCII metadata avoids escape injection, C1 controls and bidi spoofing.
|
||||
std::string out;
|
||||
for (unsigned char c : text) {
|
||||
if (out.size() == limit)
|
||||
break;
|
||||
out += c >= 32 && c < 127 ? char(c) : '?';
|
||||
}
|
||||
return out;
|
||||
}
|
||||
} // namespace crossdesk
|
||||
Reference in New Issue
Block a user