feat(host): vendor PyroWave + minimal Granite subset as crates/pyrowave-sys
Phase 0 of design/pyrowave-codec-plan.md — the opt-in wired-LAN ultra-low- latency codec. Vendored at upstream 509e4f88 (API 0.4.0, Granite 44362775, volk + vulkan-headers pins in PUNKTFUNK-VENDOR.txt), pruned to the 6.6 MB the standalone no-renderer build needs; scripts/vendor-pyrowave.sh reproduces the tree (a pin bump is protocol-affecting, plan §4.2). build.rs drives the wrapper CMakeLists (static archives incl. a static C-API lib upstream only ships shared) + bindgen over pyrowave.h; Linux and Windows only, empty stub elsewhere (Apple gets a native Metal port, §4.7). Offline-safe by construction: no network, no system lib, vendored Vulkan headers — same model as the opus dep (flatpak builder has no network). Phase-0 validation on .21 (RTX 5070 Ti, driver 610.43.03): - upstream pyrowave-c-test + interop test (incl. dmabuf/DRM-modifier Vulkan<->Vulkan) pass, from the pristine AND the pruned tree - GPU kernel times at ~1.6 bpp noise: encode/decode 0.090/0.042 ms @800p, 0.146/0.067 @1080p, 0.226/0.103 @1440p, 0.477/0.201 @4K — order of magnitude under NVENC's 1-2 ms retrieve, CBR lands within ~100 B of target - cargo test -p pyrowave-sys green (static link + API-version pin check) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
add_granite_internal_lib(granite-path path_utils.hpp path_utils.cpp)
|
||||
target_include_directories(granite-path PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(granite-path PRIVATE granite-util)
|
||||
@@ -0,0 +1,282 @@
|
||||
/* Copyright (c) 2017-2026 Hans-Kristian Arntzen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define NOMINMAX
|
||||
#include "path_utils.hpp"
|
||||
#include "string_helpers.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#ifdef __linux__
|
||||
#include <linux/limits.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace Granite
|
||||
{
|
||||
namespace Path
|
||||
{
|
||||
std::string enforce_protocol(const std::string &path)
|
||||
{
|
||||
if (path.empty())
|
||||
return "";
|
||||
|
||||
auto index = path.find("://");
|
||||
if (index == std::string::npos)
|
||||
return std::string("file://") + path;
|
||||
else
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string canonicalize_path(const std::string &path)
|
||||
{
|
||||
std::string transformed;
|
||||
transformed.resize(path.size());
|
||||
transform(begin(path), end(path), begin(transformed), [](char c) -> char { return c == '\\' ? '/' : c; });
|
||||
auto data = Util::split_no_empty(transformed, "/");
|
||||
|
||||
std::vector<std::string> result;
|
||||
for (auto &i : data)
|
||||
{
|
||||
if (i == "..")
|
||||
{
|
||||
if (!result.empty())
|
||||
result.pop_back();
|
||||
}
|
||||
else if (i != ".")
|
||||
result.push_back(std::move(i));
|
||||
}
|
||||
|
||||
std::string res;
|
||||
for (auto &i : result)
|
||||
{
|
||||
if (&i != result.data())
|
||||
res += "/";
|
||||
res += i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static size_t find_last_slash(const std::string &str)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
auto index = str.find_last_of("/\\");
|
||||
#else
|
||||
auto index = str.find_last_of('/');
|
||||
#endif
|
||||
return index;
|
||||
}
|
||||
|
||||
bool is_abspath(const std::string &path)
|
||||
{
|
||||
if (path.empty())
|
||||
return false;
|
||||
if (path.front() == '/')
|
||||
return true;
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
auto index = std::min(path.find(":/"), path.find(":\\"));
|
||||
if (index != std::string::npos)
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return path.find("://") != std::string::npos;
|
||||
}
|
||||
|
||||
bool is_root_path(const std::string &path)
|
||||
{
|
||||
if (path.empty())
|
||||
return false;
|
||||
|
||||
if (path.front() == '/' && path.size() == 1)
|
||||
return true;
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
auto index = std::min(path.find(":/"), path.find(":\\"));
|
||||
if (index != std::string::npos && (index + 2) == path.size())
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto index = path.find("://");
|
||||
return index != std::string::npos && (index + 3) == path.size();
|
||||
}
|
||||
|
||||
std::string join(const std::string &base, const std::string &path)
|
||||
{
|
||||
if (base.empty())
|
||||
return path;
|
||||
if (path.empty())
|
||||
return base;
|
||||
|
||||
if (is_abspath(path))
|
||||
return path;
|
||||
|
||||
auto index = find_last_slash(base);
|
||||
bool need_slash = index != base.size() - 1;
|
||||
return Util::join(base, need_slash ? "/" : "", path);
|
||||
}
|
||||
|
||||
std::string basedir(const std::string &path)
|
||||
{
|
||||
if (path.empty())
|
||||
return "";
|
||||
|
||||
if (is_root_path(path))
|
||||
return path;
|
||||
|
||||
auto index = find_last_slash(path);
|
||||
if (index == std::string::npos)
|
||||
return ".";
|
||||
|
||||
// Preserve the first slash.
|
||||
if (index == 0 && is_abspath(path))
|
||||
index++;
|
||||
|
||||
auto ret = path.substr(0, index + 1);
|
||||
if (!is_root_path(ret))
|
||||
ret.pop_back();
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string basename(const std::string &path)
|
||||
{
|
||||
if (path.empty())
|
||||
return "";
|
||||
|
||||
auto index = find_last_slash(path);
|
||||
if (index == std::string::npos)
|
||||
return path;
|
||||
|
||||
auto base = path.substr(index + 1, std::string::npos);
|
||||
return base;
|
||||
}
|
||||
|
||||
std::string relpath(const std::string &base, const std::string &path)
|
||||
{
|
||||
return Path::join(basedir(base), path);
|
||||
}
|
||||
|
||||
std::string ext(const std::string &path)
|
||||
{
|
||||
auto index = path.find_last_of('.');
|
||||
if (index == std::string::npos)
|
||||
return "";
|
||||
else
|
||||
return path.substr(index + 1, std::string::npos);
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string> split(const std::string &path)
|
||||
{
|
||||
if (path.empty())
|
||||
return make_pair(std::string("."), std::string("."));
|
||||
|
||||
auto index = find_last_slash(path);
|
||||
if (index == std::string::npos)
|
||||
return make_pair(std::string("."), path);
|
||||
|
||||
auto base = path.substr(index + 1, std::string::npos);
|
||||
return make_pair(path.substr(0, index), base);
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string> protocol_split(const std::string &path)
|
||||
{
|
||||
if (path.empty())
|
||||
return make_pair(std::string(""), std::string(""));
|
||||
|
||||
auto index = path.find("://");
|
||||
if (index == std::string::npos)
|
||||
return make_pair(std::string(""), path);
|
||||
|
||||
return make_pair(path.substr(0, index), path.substr(index + 3, std::string::npos));
|
||||
}
|
||||
|
||||
std::string get_executable_path()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
wchar_t target[4096];
|
||||
DWORD ret = GetModuleFileNameW(GetModuleHandle(nullptr), target, sizeof(target) / sizeof(wchar_t));
|
||||
return canonicalize_path(Path::to_utf8(target, ret));
|
||||
#else
|
||||
pid_t pid = getpid();
|
||||
static const char *exts[] = { "exe", "file", "a.out" };
|
||||
char link_path[PATH_MAX];
|
||||
char target[PATH_MAX];
|
||||
|
||||
for (auto *ext : exts)
|
||||
{
|
||||
snprintf(link_path, sizeof(link_path), "/proc/%u/%s",
|
||||
unsigned(pid), ext);
|
||||
ssize_t ret = readlink(link_path, target, sizeof(target) - 1);
|
||||
if (ret >= 0)
|
||||
{
|
||||
target[ret] = '\0';
|
||||
return std::string(target);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
std::string to_utf8(const wchar_t *wstr, size_t len)
|
||||
{
|
||||
std::vector<char> char_buffer;
|
||||
auto ret = WideCharToMultiByte(CP_UTF8, 0, wstr, len, nullptr, 0, nullptr, nullptr);
|
||||
if (ret < 0)
|
||||
return "";
|
||||
char_buffer.resize(ret);
|
||||
WideCharToMultiByte(CP_UTF8, 0, wstr, len, char_buffer.data(), char_buffer.size(), nullptr, nullptr);
|
||||
return std::string(char_buffer.data(), char_buffer.size());
|
||||
}
|
||||
|
||||
std::wstring to_utf16(const char *str, size_t len)
|
||||
{
|
||||
std::vector<wchar_t> wchar_buffer;
|
||||
auto ret = MultiByteToWideChar(CP_UTF8, 0, str, len, nullptr, 0);
|
||||
if (ret < 0)
|
||||
return L"";
|
||||
wchar_buffer.resize(ret);
|
||||
MultiByteToWideChar(CP_UTF8, 0, str, len, wchar_buffer.data(), wchar_buffer.size());
|
||||
return std::wstring(wchar_buffer.data(), wchar_buffer.size());
|
||||
}
|
||||
|
||||
std::string to_utf8(const std::wstring &wstr)
|
||||
{
|
||||
return to_utf8(wstr.data(), wstr.size());
|
||||
}
|
||||
|
||||
std::wstring to_utf16(const std::string &str)
|
||||
{
|
||||
return to_utf16(str.data(), str.size());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/* Copyright (c) 2017-2026 Hans-Kristian Arntzen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace Granite
|
||||
{
|
||||
namespace Path
|
||||
{
|
||||
std::string join(const std::string &base, const std::string &path);
|
||||
std::string basedir(const std::string &path);
|
||||
std::string basename(const std::string &path);
|
||||
std::pair<std::string, std::string> split(const std::string &path);
|
||||
std::string relpath(const std::string &base, const std::string &path);
|
||||
std::string ext(const std::string &path);
|
||||
std::pair<std::string, std::string> protocol_split(const std::string &path);
|
||||
bool is_abspath(const std::string &path);
|
||||
bool is_root_path(const std::string &path);
|
||||
std::string canonicalize_path(const std::string &path);
|
||||
std::string enforce_protocol(const std::string &path);
|
||||
std::string get_executable_path();
|
||||
|
||||
#ifdef _WIN32
|
||||
std::string to_utf8(const wchar_t *wstr, size_t len);
|
||||
std::wstring to_utf16(const char *str, size_t len);
|
||||
std::string to_utf8(const std::wstring &wstr);
|
||||
std::wstring to_utf16(const std::string &str);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user