增加文件缓存模块

main
wangchongwu 5 months ago
parent d04e0234f2
commit 8ad78387ea

@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.5.0)
project(stitch VERSION 0.1.0 LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
SET(ArithStitchDir stitch)
IF(WIN32)

@ -7,3 +7,6 @@
【初步设想】:建立二级文件缓存,其中第一级存储原始帧(图像+H矩阵等第二级存储生成的标准瓦片。当系统工作时根据当前视野范围和XYZ瓦片等级X开始从2级缓存搜索瓦片如果存在瓦片则直接加载如果不存在则从1级缓存读取原始帧生成瓦片并将瓦片加入2级缓存。
【关键技术】:文件缓存技术、标准瓦片转换技术
- 2 20250205
上述开发计划存在问题,拼接算法应是后台服务,应当生成标准产品,而不随着显示更改逻辑,这里考虑生成谷歌瓦片,并通过流传输到显示端,由显控处理显示逻辑。

@ -4,8 +4,26 @@
#include "PlatformDefine.h"
#include <string.h>
#include "opencv2/opencv.hpp"
#include <random>
using namespace std;
using namespace cv;
class GaussianRandom {
public:
GaussianRandom(double mean = 0.0, double stddev = 1.0, double amplitude = 1.0)
: generator(std::random_device{}()),
distribution(mean, stddev),
amplitude(amplitude) {}
double generate() {
return amplitude * distribution(generator);
}
private:
std::mt19937 generator;
std::normal_distribution<double> distribution;
double amplitude;
};
void Map16BitTo8Bit(unsigned short *psh16BitData, long lDataLen, BYTE *pby8BitData)
{
@ -92,10 +110,12 @@ int main(int, char**)
GD_VIDEO_FRAME_S pan = { 0 };//输出全景
cv::Mat mat_pan;//全景显示
//return 0;
FILE* file = fopen("../20241219152917_4.xraw","rb");
//FILE* file = fopen("/media/wang/WORK/wangchongwu_gitea_2023/20241219152917_4.xraw","rb");
FILE* file = fopen("D:/wangchongwu_gitea_2023/20241219152917_4.xraw", "rb");
//FILE* file = fopen("/home/wang/data62/729dataset/ir_1280_1024_para40_y16/5.xraw","rb");
GaussianRandom gr(0.0, 1, 0.2);
for (size_t i = 0; i < 600; i++)
{
@ -104,7 +124,6 @@ int main(int, char**)
S729paras_IR Paras_IR = { 0 };
memcpy(&Paras_IR, (unsigned char*)(pFrameIR + IMAGE_WIDTH_IR*IMAGE_HEIGHT_IR), sizeof(S729paras_IR));
FrameInfo info = {0};
info.nFrmID = i;
@ -128,6 +147,12 @@ int main(int, char**)
info.nWidth = IMAGE_WIDTH_IR;
info.nHeight = IMAGE_HEIGHT_IR;
info.craft.stAtt.fYaw += gr.generate();
info.craft.stAtt.fPitch += gr.generate();
info.craft.stAtt.fRoll += gr.generate();
Map16BitTo8Bit(pFrameIR,IMAGE_WIDTH_IR*IMAGE_HEIGHT_IR,pImageIR);
cv::Mat mat_src(IMAGE_HEIGHT_IR, IMAGE_WIDTH_IR, CV_8UC1, pImageIR);
@ -156,24 +181,32 @@ int main(int, char**)
{
continue;
}
cout << info.craft.stPos.B << " " <<info.craft.stPos.L << " " << info.craft.stPos.H << " "
std::cout << info.craft.stPos.B << " " <<info.craft.stPos.L << " " << info.craft.stPos.H << " "
<< info.craft.stAtt.fYaw << " " << info.craft.stAtt.fPitch << " " << info.craft.stAtt.fRoll<< " "
<< info.servoInfo.fServoAz << " " << info.servoInfo.fServoPt
<< endl;
<< std::endl;
// 基于地理系的拼接
//stitcher->GeoStitch(frame,info);
// 基于地理+BA拼接
auto nNum = stitcher->BAStitch(frame,info);
//auto nNum = stitcher->BAStitch(frame,info);
// test接口
//if (info.nFrmID == 30 || info.nFrmID == 40)
{
auto a = stitcher->ReceiveFrame(frame,info);
}
stitcher->ProcFrame();
//cout << nNum << endl;
//imshow("src", mat_src);
//waitKey(0);
//waitKey(1);
}
// imshow("pan", mat_pan);
//imshow("pan", mat_pan);
// waitKey(1);
@ -182,7 +215,7 @@ int main(int, char**)
// 读入所有帧执行一次全局BA
stitcher->BAOpt();
//stitcher->BAOpt();
//waitKey(0);

@ -12,23 +12,20 @@ endif()
IF(WIN32)
set(OpenCV_DIR "D:/opencv410_vc17")
set(CMAKE_TOOLCHAIN_FILE "D:/wangchongwu_gitea_2023/vcpkg-2025.01.13/scripts/buildsystems/vcpkg.cmake")
set(Ceres_DIR "C:/Lib/ceres")
ELSE(WIN32)
set(OpenCV_DIR "/home/wcw/opencv-3.4.16/install/share/OpenCV")
ENDIF(WIN32)
ENDIF(WIN32)
find_package(Ceres REQUIRED)
include_directories(${CERES_INCLUDE_DIRS})
find_package(OpenMP REQUIRED)
include_directories(${CERES_INCLUDE_DIRS})
#
SET(ArithTrkPubInc ${CMAKE_SOURCE_DIR}/public_include)
include_directories(${ArithTrkPubInc}) #
@ -37,9 +34,6 @@ include_directories(${ArithTrkPubInc}) # 引入算法公共头文件
link_directories(${OpenCV_LIBS_DIR})
include_directories(${OpenCV_INCLUDE_DIRS})
set(ArithSrcDIR_MAIN "src") #
# 使Common
@ -60,16 +54,15 @@ target_link_libraries(${LIB_STITCH}
OpenMP::OpenMP_CXX
${OpenCV_LIBS}
${CERES_LIBRARIES}
)
)
# # gcc0
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
#
add_definitions(-fvisibility=hidden)
# # # gcc0
# if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# #
# add_definitions(-fvisibility=hidden)
#
target_compile_options(${LIB_STITCH} PRIVATE -Werror -Wreturn-type)
endif()
# #
# target_compile_options(${LIB_STITCH} PRIVATE -Werror -Wreturn-type)
# endif()
set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/Bin) #

@ -36,6 +36,10 @@ public:
// 获取全景图
virtual GD_VIDEO_FRAME_S ExportPanAddr() = 0;
virtual SINT32 ReceiveFrame(GD_VIDEO_FRAME_S img, FrameInfo para) = 0;
virtual SINT32 ProcFrame() = 0;
public:
static API_VideoStitch* Create(SINT32 nWidth, SINT32 nHeight);
static void Destroy(API_VideoStitch* obj);

@ -128,7 +128,7 @@ void BA_Task::Test()
//#define SHOW_MATCH
void BA_Task::optimizeBA()
{
remap(_origMatrix, "_origMatrix");
//remap(_origMatrix, "_origMatrix");
// 计算匹配性矩阵
CalMatchMat(0.3);
@ -192,7 +192,7 @@ void BA_Task::optimizeBA()
_FeaMatcher->matchFeatures_WithH(_FeaPtVec[i], _FeaDespVec[i], _FeaPtVec[j], _FeaDespVec[j], _origMatrix[i], _origMatrix[j], matches);
// 图像特征匹配点对超过N对才认为有效
if (matches.size() > 50)
if (matches.size() > 20)
{
_MatchMat.at<int>(i, j) = matches.size();
_MatchMat.at<int>(j, i) = matches.size();
@ -231,7 +231,7 @@ void BA_Task::optimizeBA()
cv::KeyPoint keypoint_i = _FeaPtVec[i][mc.queryIdx];
cv::KeyPoint keypoint_j = _FeaPtVec[j][mc.trainIdx];
ceres::LossFunction* loss_function = new ceres::HuberLoss(15);
ceres::LossFunction* loss_function = new ceres::HuberLoss(35);
cv::Mat H1 = _origMatrix[i];
cv::Mat H2 = _origMatrix[j];
@ -249,7 +249,7 @@ void BA_Task::optimizeBA()
// 配置求解器
ceres::Solver::Options options;
options.max_num_iterations = 1; // 增加最大迭代次数
options.max_num_iterations = 6; // 增加最大迭代次数
options.function_tolerance = 1e-8; // 设置更严格的函数值容忍度
options.gradient_tolerance = 1e-10; // 设置更严格的梯度容忍度
options.parameter_tolerance = 1e-10; // 设置更严格的参数容忍度
@ -274,7 +274,7 @@ void BA_Task::optimizeBA()
std::cout << summary.BriefReport() << std::endl;
remap(_currMatrix, "_currMatrix");
//remap(_currMatrix, "_currMatrix");
cv::waitKey(0);

@ -26,6 +26,8 @@ VideoStitch::VideoStitch(SINT32 nWidth, SINT32 nHeight)
memset(&_pan, 0, sizeof(GD_VIDEO_FRAME_S));
_BATask = new BA_Task(_GeoStitcher);
_cache = new FileCache(5,"./cache");
}
VideoStitch::~VideoStitch()
@ -119,6 +121,71 @@ SINT32 VideoStitch::BAOpt()
return 0;
}
SINT32 VideoStitch::ReceiveFrame(GD_VIDEO_FRAME_S img, FrameInfo para)
{
cout << "recv:" << para.nFrmID << endl;
// 构造单帧缓存
auto _t_frame_cache = std::make_shared<FrameCache>();
_t_frame_cache->_para = para;
_t_frame_cache->_frame_info = img;
int imgSize = 0;
if(img.enPixelFormat == GD_PIXEL_FORMAT_GRAY_Y8)
{
imgSize = img.u32Height * img.u32Width;
}
if(img.enPixelFormat == GD_PIXEL_FORMAT_RGB_PACKED)
{
imgSize = img.u32Height * img.u32Width * 3;
}
// 深拷贝图像数据
memcpy(_t_frame_cache->_data,img.u64VirAddr[0],imgSize);
auto size = sizeof(_t_frame_cache);
// 加入文件缓存
_cache->set(para.nFrmID,_t_frame_cache);
return SINT32();
}
SINT32 VideoStitch::ProcFrame()
{
printf("size:%d\n",_cache->getMemSize());
std::shared_ptr<FrameCache> loadedFrame1;
bool bflag1 = _cache->get(30, loadedFrame1);
std::shared_ptr<FrameCache> loadedFrame2;
auto bflag2 = _cache->get(40,loadedFrame2);
if (bflag1 && loadedFrame1->_frame_info.u32Height > 0)
{
cv::Mat src1(loadedFrame1->_frame_info.u32Height, loadedFrame1->_frame_info.u32Width, CV_8UC1, loadedFrame1->_data);
imshow("src30",src1);
waitKey(1);
}
if (bflag2 && loadedFrame2->_frame_info.u32Height > 0)
{
cv::Mat src2(loadedFrame2->_frame_info.u32Height, loadedFrame2->_frame_info.u32Width, CV_8UC1, loadedFrame2->_data);
imshow("src40",src2);
waitKey(0);
}
return 0;
}
GD_VIDEO_FRAME_S VideoStitch::ExportPanAddr()
{
GD_VIDEO_FRAME_S pan_out;

@ -4,6 +4,7 @@
#include "Arith_FeaMatch.h"
#include "StitchStruct.h"
#include "Arith_BATask.h"
#include "FileCache.h"
class VideoStitch:public API_VideoStitch
{
@ -22,10 +23,18 @@ public:
SINT32 BAStitch(GD_VIDEO_FRAME_S img, FrameInfo para);
SINT32 BAOpt();
// 接收帧
SINT32 ReceiveFrame(GD_VIDEO_FRAME_S img, FrameInfo para);
// 处理帧
SINT32 ProcFrame();
GD_VIDEO_FRAME_S ExportPanAddr();
private:
FileCache* _cache;//文件缓存,存储外部传入的原始帧信息以及预处理结果
private:

@ -0,0 +1,124 @@
#include "FileCache.h"
#include <fstream>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
// 计算哈希值并转成字符串作为文件名
static std::string hashKey(const KeyType& key)
{
std::hash<KeyType> hasher;
return std::to_string(hasher(key));
}
FileCache::FileCache(size_t max_size, const std::string& cache_dir)
: max_size_(max_size), cache_dir_(cache_dir)
{
// 确保缓存目录存在
if (!fs::exists(cache_dir_))
{
fs::create_directories(cache_dir_);
}
}
std::string FileCache::getCacheFilePath(const KeyType& key) const
{
return cache_dir_ + "/" + hashKey(key) + ".cache"; // 使用哈希作为文件名
}
void FileCache::saveToFile(const KeyType& key, const FrameCache& frame)
{
std::string filePath = getCacheFilePath(key);
std::ofstream ofs(filePath, std::ios::binary);
if (ofs)
{
ofs.write(reinterpret_cast<const char*>(&frame), sizeof(frame));
}
}
bool FileCache::loadFromFile(const KeyType& key, FrameCache& frame)
{
std::string filePath = getCacheFilePath(key);
std::ifstream ifs(filePath, std::ios::binary);
if (!ifs)
{
return false;
}
ifs.read(reinterpret_cast<char*>(&frame), sizeof(frame));
return true;
}
void FileCache::evictIfNeeded()
{
if (cache_.size() < max_size_)
return;
// 删除最早使用的LRU 末尾)
KeyType oldest = lru_list_.back();
lru_list_.pop_back();
cache_.erase(oldest);
std::cout << "Evicted cache from memory for key: " << oldest << std::endl;
}
bool FileCache::get(const KeyType& key, std::shared_ptr<FrameCache>& pData)
{
std::lock_guard<std::mutex> lock(mutex_);
// 检查内存缓存
auto it = cache_.find(key);
if (it != cache_.end())
{
// 缓存命中,更新 LRU 顺序
lru_list_.erase(it->second.second);
lru_list_.push_front(key);
it->second.second = lru_list_.begin();
pData = it->second.first;
return true;
}
// 尝试从文件加载
auto newData = std::make_shared<FrameCache>();
if (loadFromFile(key, *newData))
{
evictIfNeeded(); // 超出内存容量时删除最早的
// 插入新缓存到内存
lru_list_.push_front(key);
cache_[key] = {newData, lru_list_.begin()};
pData = newData;
return true;
}
return false;
}
void FileCache::set(const KeyType& key, std::shared_ptr<FrameCache> pData)
{
std::lock_guard<std::mutex> lock(mutex_);
// 如果已存在,则更新 LRU 位置
auto it = cache_.find(key);
if (it != cache_.end())
{
lru_list_.erase(it->second.second);
}
else
{
evictIfNeeded(); // 超出内存容量时删除最早的
}
// 插入新数据到内存
lru_list_.push_front(key);
cache_[key] = {pData, lru_list_.begin()};
saveToFile(key, *pData); // 将数据存储到磁盘
}
size_t FileCache::getMemSize()
{
std::lock_guard<std::mutex> lock(mutex_);
return cache_.size();
}

@ -0,0 +1,38 @@
#pragma once
#include <unordered_map>
#include <list>
#include <mutex>
#include <memory>
#include <opencv2/core.hpp>
#include <fstream>
#include <string>
#include <filesystem>
#include "StitchStruct.h"
//
using KeyType = int;
class FileCache
{
public:
explicit FileCache(size_t max_size, const std::string& cache_dir = "./cache");
bool get(const KeyType& key, std::shared_ptr<FrameCache>& pData);
void set(const KeyType& key, std::shared_ptr<FrameCache> pData);
size_t getMemSize();
private:
size_t max_size_;
std::string cache_dir_;
std::unordered_map<KeyType, std::pair<std::shared_ptr<FrameCache>, std::list<KeyType>::iterator>> cache_;
std::list<KeyType> lru_list_;
std::mutex mutex_;
bool loadFromFile(const KeyType& key, FrameCache& frame);
void saveToFile(const KeyType& key, const FrameCache& frame);
void evictIfNeeded();
std::string getCacheFilePath(const KeyType& key) const;
};

@ -38,4 +38,14 @@ struct Match_Net
int imgNo; //! image no. start from 0
vector<int> relatedImgs; //! the position index of overlap-image in visitOrder
vector<vector<Point2d> > PointSet;
};
// 帧缓存
struct FrameCache
{
FrameInfo _para;
GD_VIDEO_FRAME_S _frame_info;
BYTE8 _data[1920*1080];
cv::Point2f _pt[500];
};

@ -1,179 +0,0 @@
#include "FileCache.h"
#include <fstream>
#include <sstream>
#include <iomanip>
#include <stdexcept>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#endif
namespace fs = std::filesystem;
FileCache::FileCache(const std::string& cache_dir, size_t max_memory_items)
: cache_dir_(cache_dir), max_memory_items_(max_memory_items)
{
fs::create_directories(cache_dir_);
}
FileCache::~FileCache()
{
// Clean up memory-mapped files
for (auto& [key, mapped_file] : mapped_files_) {
if (mapped_file.data) {
unmap_file(mapped_file.data, mapped_file.size);
}
}
}
std::string FileCache::hash_key(const std::string& key) const
{
// Simple hash function (replace with a better one if needed)
std::hash<std::string> hasher;
size_t hash_value = hasher(key);
std::ostringstream hex_stream;
hex_stream << std::hex << hash_value;
return hex_stream.str();
}
std::string FileCache::get_file_path(const std::string& key) const
{
std::string hashed = hash_key(key);
std::string sub_dir = cache_dir_ + "/" + hashed.substr(0, 2);
fs::create_directories(sub_dir);
return sub_dir + "/" + hashed.substr(2) + ".cache";
}
template<typename T>
std::optional<T> FileCache::get(const std::string& key)
{
{
std::lock_guard<std::mutex> lock(cache_mutex_);
if (memory_cache_.count(key)) {
const auto& data = memory_cache_[key];
return *reinterpret_cast<const T*>(data.data());
}
if (mapped_files_.count(key)) {
const auto& mapped_file = mapped_files_[key];
return *reinterpret_cast<const T*>(mapped_file.data);
}
}
auto file_path = get_file_path(key);
return load_from_disk<T>(file_path);
}
template<typename T>
void FileCache::set(const std::string& key, const T& data)
{
auto serialized = std::vector<uint8_t>(reinterpret_cast<const uint8_t*>(&data),
reinterpret_cast<const uint8_t*>(&data) + sizeof(T));
{
std::lock_guard<std::mutex> lock(cache_mutex_);
memory_cache_[key] = serialized;
// Evict if necessary
if (memory_cache_.size() > max_memory_items_)
{
memory_cache_.erase(memory_cache_.begin());
}
}
// Async save to disk
auto file_path = get_file_path(key);
async_tasks_.push_back(std::async(std::launch::async, [this, file_path, serialized]() {
save_to_disk(file_path, serialized);
}));
}
template<typename T>
bool FileCache::save_to_disk(const std::string& file_path, const T& data)
{
std::ofstream out(file_path, std::ios::binary);
if (!out) return false;
out.write(reinterpret_cast<const char*>(&data), sizeof(data));
return true;
}
template<typename T>
std::optional<T> FileCache::load_from_disk(const std::string& file_path) const
{
size_t file_size = fs::file_size(file_path);
void* mapped_data = map_file(file_path, file_size);
if (!mapped_data)
{
return std::nullopt;
}
// Store the mapped file for later use
std::lock_guard<std::mutex> lock(cache_mutex_);
mapped_files_[file_path] = {mapped_data, file_size};
return *reinterpret_cast<const T*>(mapped_data);
}
void FileCache::clear()
{
std::lock_guard<std::mutex> lock(cache_mutex_);
memory_cache_.clear();
for (const auto& [key, mapped_file] : mapped_files_) {
if (mapped_file.data)
{
unmap_file(mapped_file.data, mapped_file.size);
}
}
mapped_files_.clear();
for (const auto& entry : fs::directory_iterator(cache_dir_))
{
fs::remove_all(entry.path());
}
}
// Platform-specific memory mapping
void* FileCache::map_file(const std::string& file_path, size_t size)
{
#ifdef _WIN32
HANDLE file = CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (file == INVALID_HANDLE_VALUE) return nullptr;
HANDLE mapping = CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr);
if (!mapping)
{
CloseHandle(file);
return nullptr;
}
void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, size);
CloseHandle(mapping);
CloseHandle(file);
return data;
#else
int fd = open(file_path.c_str(), O_RDONLY);
if (fd == -1) return nullptr;
void* data = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
if (data == MAP_FAILED) {
return nullptr;
}
return data;
#endif
}
void FileCache::unmap_file(void* data, size_t size)
{
#ifdef _WIN32
UnmapViewOfFile(data);
#else
munmap(data, size);
#endif
}

@ -0,0 +1,229 @@
#include "FileCache.h"
#include <fstream>
#include <sstream>
#include <iomanip>
#include <stdexcept>
#include "StitchStruct.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#endif
#include "openssl/sha.h"
namespace fs = std::filesystem;
FileCache::FileCache(const std::string& cache_dir, size_t max_memory_items)
: cache_dir_(cache_dir), max_memory_items_(max_memory_items)
{
fs::create_directories(cache_dir_);
}
FileCache::~FileCache()
{
// Clean up memory-mapped files
for (auto& [key, mapped_file] : mapped_files_)
{
unmap_file(&mapped_file, sizeof(FrameCache));
}
}
std::string FileCache::hash_key(const KeyType& key) const
{
// Convert key to a string representation
std::string key_str = std::to_string(key);
// Compute SHA-256 hash
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, key_str.c_str(), key_str.size());
SHA256_Final(hash, &sha256);
// Convert hash to a hex string
std::ostringstream hex_stream;
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
hex_stream << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
}
return hex_stream.str();
}
std::string FileCache::get_file_path(const KeyType& key) const
{
std::string hashed = hash_key(key);
return cache_dir_ + "/" + hashed.substr(2) + ".cache";
}
bool FileCache::get(KeyType key,FrameCache* pData)
{
{
std::lock_guard<std::mutex> lock(cache_mutex_);
if (memory_cache_.count(key))
{
memcpy(pData,&memory_cache_[key],sizeof(FrameCache));
std::cout << "get from memory_cache_:" << pData->_para.nFrmID << std::endl;
return true;
}
if (mapped_files_.count(key))
{
memcpy(pData,&mapped_files_[key],sizeof(FrameCache));
std::cout << "get from mapped_files_:" << pData->_para.nFrmID << std::endl;
return true;
}
}
auto file_path = get_file_path(key);
return load_from_disk(file_path,key,pData);
}
void FileCache::set(KeyType key, FrameCache* pData)
{
std::lock_guard<std::mutex> lock(cache_mutex_);
memcpy(&memory_cache_[key],pData,sizeof(FrameCache));
std::cout << "set memory_cache:" << memory_cache_[key]._para.nFrmID <<std::endl;
// Evict if necessary
if (memory_cache_.size() > max_memory_items_)
{
memory_cache_.erase(memory_cache_.begin());
}
// Async save to disk
auto file_path = get_file_path(key);
//save_to_disk(file_path, pData);
async_tasks_.push_back(std::async(std::launch::async, [this, file_path, pData]() {
save_to_disk(file_path, pData);
}));
}
bool FileCache::save_to_disk(const std::string& file_path, FrameCache* data)
{
std::ofstream out(file_path, std::ios::binary);
if (!out) return false;
auto nsize = sizeof(FrameCache);
//std::cout << "set file:" << data->_para.nFrmID <<std::endl;
out.write(reinterpret_cast<const char*>(data), sizeof(FrameCache));
return true;
}
bool FileCache::load_from_disk(const std::string& file_path,const KeyType& key,FrameCache* pData)
{
if (!fs::exists(file_path))
{
return false;
}
const char* str = file_path.c_str();
size_t file_size = fs::file_size(file_path);
void* mapped_data = map_file(file_path, file_size);
if (!mapped_data)
{
return false;
}
// Store the mapped file for later use
std::lock_guard<std::mutex> lock(cache_mutex_);
FrameCache* ptr = &mapped_files_[key];
// 存储到文件映射中
memcpy(ptr,mapped_data,sizeof(FrameCache));
// 返回
memcpy(pData,mapped_data,sizeof(FrameCache));
std::cout << "get from raw_files_:" << pData->_para.nFrmID << std::endl;
return true;
}
void FileCache::clear()
{
std::lock_guard<std::mutex> lock(cache_mutex_);
memory_cache_.clear();
for (const auto& [key, mapped_file] : mapped_files_)
{
unmap_file((void*)&mapped_file, sizeof(FrameCache));
}
mapped_files_.clear();
for (const auto& entry : fs::directory_iterator(cache_dir_))
{
fs::remove_all(entry.path());
}
}
SINT32 FileCache::get_mem_size()
{
return memory_cache_.size();
}
SINT32 FileCache::get_file_size()
{
return mapped_files_.size();
}
// Platform-specific memory mapping
void* FileCache::map_file(const std::string& file_path, size_t size)
{
#ifdef _WIN32
HANDLE file = CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (file == INVALID_HANDLE_VALUE) return nullptr;
HANDLE mapping = CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr);
if (!mapping)
{
CloseHandle(file);
return nullptr;
}
void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, size);
CloseHandle(mapping);
CloseHandle(file);
return data;
#else
int fd = open(file_path.c_str(), O_RDONLY);
if (fd == -1) return nullptr;
void* data = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
if (data == MAP_FAILED) {
return nullptr;
}
return data;
#endif
}
void FileCache::unmap_file(void* data, size_t size)
{
#ifdef _WIN32
UnmapViewOfFile(data);
#else
munmap(data, size);
#endif
}

@ -1,55 +0,0 @@
#pragma once
#include <string>
#include <unordered_map>
#include <mutex>
#include <future>
#include <filesystem>
#include <optional>
#include <vector>
#include <cstdint>
class FileCache
{
public:
FileCache(const std::string& cache_dir = "./tile_cache", size_t max_memory_items = 1000);
~FileCache();
template<typename T>
std::optional<T> get(const std::string& key);
template<typename T>
void set(const std::string& key, const T& data);
void clear();
private:
std::string get_file_path(const std::string& key) const;
std::string hash_key(const std::string& key) const;
template<typename T>
bool save_to_disk(const std::string& file_path, const T& data);
template<typename T>
std::optional<T> load_from_disk(const std::string& file_path) const;
std::string cache_dir_;
size_t max_memory_items_;
// Memory cache
mutable std::mutex cache_mutex_;
std::unordered_map<std::string, std::vector<uint8_t>> memory_cache_;
// Memory-mapped files
struct MappedFile {
void* data;
size_t size;
};
std::unordered_map<std::string, MappedFile> mapped_files_;
// Async tasks
std::vector<std::future<void>> async_tasks_;
// Platform-specific memory mapping
void* map_file(const std::string& file_path, size_t size);
void unmap_file(void* data, size_t size);
};

@ -0,0 +1,56 @@
#pragma once
#include <string>
#include <unordered_map>
#include <mutex>
#include <future>
#include <filesystem>
#include <optional>
#include <vector>
#include <cstdint>
#include "StitchStruct.h"
typedef int KeyType;
class FileCache
{
public:
FileCache(const std::string& cache_dir = "./tile_cache", size_t max_memory_items = 200);
~FileCache();
bool get(KeyType key,FrameCache* pData);
void set(KeyType key, FrameCache* pData);
void clear();
SINT32 get_mem_size();
SINT32 get_file_size();
private:
std::string get_file_path(const KeyType& key) const;
std::string hash_key(const KeyType& key) const;
bool save_to_disk(const std::string& file_path, FrameCache* data);
bool load_from_disk(const std::string& file_path,const KeyType& key,FrameCache* pData);
std::string cache_dir_;
size_t max_memory_items_;
// Memory cache
mutable std::mutex cache_mutex_;
std::unordered_map<KeyType, FrameCache> memory_cache_;
std::unordered_map<KeyType, FrameCache> mapped_files_;
// Async tasks
std::vector<std::future<void>> async_tasks_;
// Platform-specific memory mapping
void* map_file(const std::string& file_path, size_t size);
void unmap_file(void* data, size_t size);
};
Loading…
Cancel
Save