code_device/hgdriver/hgdev/hg_ipc.cpp

867 lines
18 KiB
C++
Raw Normal View History

2022-05-03 03:56:07 +00:00
#include "hg_ipc.h"
#include "../wrapper/hg_log.h"
2022-05-03 03:56:07 +00:00
#include "huagao/hgscanner_error.h"
#if defined(WIN32) || defined(_WIN64)
2022-06-16 08:03:55 +00:00
//#include "scanner_manager.h"
2022-05-03 03:56:07 +00:00
#else
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
2022-05-03 03:56:07 +00:00
#include <unistd.h>
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// memory management ...
void* allocate_memory(size_t bytes, const char* log_msg)
{
bytes += 7;
bytes /= 8;
bytes *= 8;
return new char[bytes];
}
void free_memory(void* ptr)
{
if (ptr)
delete[] ptr;
}
2022-05-03 03:56:07 +00:00
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// windows event ...
#if defined(WIN32) || defined(_WIN64)
2022-05-03 03:56:07 +00:00
int __stdcall sem_init(sem_t* handle, int, int)
{
if (!handle)
{
errno = EINVAL;
return -1;
}
*handle = CreateEvent(NULL, TRUE, FALSE, NULL);
if (*handle)
return 0;
else
{
errno = GetLastError();
return -1;
}
}
void __stdcall sem_destroy(sem_t* handle)
{
if (*handle)
{
CloseHandle(*handle);
*handle = NULL;
}
}
int __stdcall sem_trywait(sem_t* handle)
{
return WaitForSingleObject(*handle, 1) == WAIT_TIMEOUT ? -1 : 0;
}
void __stdcall sem_wait(sem_t* handle)
{
if(WaitForSingleObject(*handle, INFINITE) == WAIT_OBJECT_0)
ResetEvent(*handle);
}
int __stdcall sem_timedwait(sem_t* handle, struct timespec* to)
{
DWORD elapse = to->tv_sec * 1000;
elapse += to->tv_nsec / (1000 * 1000);
int ret = WaitForSingleObject(*handle, elapse) == WAIT_TIMEOUT ? -1 : 0;
if(ret == 0)
ResetEvent(*handle);
return ret;
}
void __stdcall sem_post(sem_t* handle)
{
SetEvent(*handle);
}
#define pid_t int
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// platform_event (base on semaphore)
platform_event::platform_event() : waiting_(false), dbg_info_("")
{
int err = sem_init(&sem_, 0, 0);
if (err == -1)
{
err = errno;
VLOG_MINI_2(LOG_LEVEL_FATAL, "(%s)sem_init failed: %d\n", hg_log::format_ptr(this).c_str(), err);
2022-05-03 03:56:07 +00:00
}
}
platform_event::~platform_event()
{
sem_destroy(&sem_);
}
bool platform_event::try_wait(void)
{
return sem_trywait(&sem_) == 0;
}
bool platform_event::wait(unsigned timeout)
{
bool waited = true;
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "platform_event(%s - %s) --> waiting...\n", hg_log::format_ptr(this).c_str(), dbg_info_.c_str());
2022-05-03 03:56:07 +00:00
waiting_ = true;
if (timeout == USB_TIMEOUT_INFINITE)
sem_wait(&sem_);
else
{
struct timespec to;
to.tv_sec = timeout / 1000;
to.tv_nsec = (long)((timeout % 1000) * 1000 * 1000);
waited = sem_timedwait(&sem_, &to) == 0;
}
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "platform_event(%s - %s) --> %s.\n", hg_log::format_ptr(this).c_str(), dbg_info_.c_str(), waited ? "waited" : "wait timeout");
2022-05-03 03:56:07 +00:00
waiting_ = false;
return waited;
}
void platform_event::notify(void)
{
sem_post(&sem_);
}
bool platform_event::is_waiting(void)
{
return waiting_;
}
void platform_event::set_debug_info(const char* info)
{
dbg_info_ = info ? info : "";
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// shared_memory
shared_memory::shared_memory(unsigned long long key, size_t size) : key_(key), obj_((void*)-1), first_(true), bytes_(size), len_(0)
{
unsigned int* ptr = (unsigned int*)&key_;
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "shared memory key = 0x%x%08x\n", ptr[1], ptr[0]);
2022-05-03 03:56:07 +00:00
init();
}
shared_memory::~shared_memory()
{
clear();
}
void shared_memory::init(void)
{
#if defined(WIN32) || defined(_WIN64)
2022-05-03 03:56:07 +00:00
char name[40] = { 0 };
DWORD* key = (DWORD*)&key_;
HANDLE h = NULL;
sprintf(name, "scanner_0x%08x-%08x", key[1], key[0]);
h = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, bytes_, name);
if (h == NULL)
return;
first_ = !(GetLastError() == ERROR_ALREADY_EXISTS);
obj_ = (void*)h;
#else
int obj = shmget(key_, bytes_, IPC_EXCL | IPC_CREAT | 0600);
if (obj < 0)
{
2022-05-16 09:26:36 +00:00
unsigned int* v = (unsigned int*)&key_;
2022-05-03 03:56:07 +00:00
if (errno == EEXIST)
{
first_ = false;
obj = shmget(key_, bytes_, 0600);
2022-05-16 09:26:36 +00:00
if(obj == -1)
obj = shmget(key_, bytes_, 0);
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "open existing: shmget(0x%x%08x) = %d\n", v[1], v[0], obj);
2022-05-16 09:26:36 +00:00
obj_ = (void*)obj;
std::string prev(read()), proc("");
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "shared memory content: %s\n", prev.c_str());
2022-05-16 09:26:36 +00:00
if(prev.length())
{
proc = prev;
size_t pos = proc.find("pid: ");
if (pos != std::string::npos)
proc.erase(0, pos + 5);
pos = proc.find(")");
if (pos != std::string::npos)
proc.erase(pos);
proc = shared_memory::get_proc_name_by_pid(atoi(proc.c_str()));
if (proc.length())
{
pos = prev.find("(");
if (pos == std::string::npos)
pos = prev.length();
if (strcasecmp(proc.c_str(), prev.substr(0, pos).c_str()))
proc = "";
}
}
if (proc.empty())
2022-05-03 03:56:07 +00:00
{
first_ = true;
clear();
obj = shmget(key_, bytes_, IPC_EXCL | IPC_CREAT | 0600);
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%s is not existing and reopen it\n", prev.c_str());
2022-05-03 03:56:07 +00:00
}
}
else
2022-05-16 09:26:36 +00:00
{
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "shmget(0x%x%08x) = %d\n", v[1], v[0], errno);
2022-05-03 03:56:07 +00:00
return;
2022-05-16 09:26:36 +00:00
}
2022-05-03 03:56:07 +00:00
}
obj_ = (void*)obj;
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "shared memory id = %d[%s], \n", obj, first_ ? "created" : "opened");
2022-05-03 03:56:07 +00:00
#endif
if(first_)
{
pid_t pid = getpid();
std::string me("");
char buf[40] = { 0 };
unsigned int* pn = (unsigned int*)&pid;
if (sizeof(pid) > 4 && pn[1])
sprintf(buf, "(pid: 0x%x%08x)", pn[1], pn[0]);
else
sprintf(buf, "(pid: %u)", pn[0]);
hg_log::pe_path(&me);
me += buf;
write(me.c_str(), me.length());
}
}
void shared_memory::clear(void)
{
if (obj_ != (void*)-1)
#if defined(WIN32) || defined(_WIN64)
2022-05-03 03:56:07 +00:00
CloseHandle((HANDLE)obj_);
#else
{
if (first_)
{
struct shmid_ds ds = { 0 };
int* h = (int*)&obj_;
shmctl(*h, IPC_RMID, &ds);
}
}
#endif
obj_ = (void*)-1;
}
char* shared_memory::get_buf(void)
{
#if defined(WIN32) || defined(_WIN64)
2022-05-03 03:56:07 +00:00
char* buf = (char*)MapViewOfFile((HANDLE)obj_, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
if (!buf)
buf = (char*)-1;
#else
int* h = (int*)&obj_;
char* buf = (char*)shmat(*h, 0, 0);
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "shared memory %d buffer = %s, error = %d\n", *h, hg_log::format_ptr(buf).c_str(), errno);
2022-05-03 03:56:07 +00:00
#endif
return buf;
}
void shared_memory::release_buf(void* buf)
{
#if defined(WIN32) || defined(_WIN64)
2022-05-03 03:56:07 +00:00
UnmapViewOfFile(buf);
#else
shmdt(buf);
#endif
}
#if !defined(WIN32) && !defined(_WIN64)
2022-05-16 09:26:36 +00:00
std::string shared_memory::get_proc_name_by_pid(pid_t pid)
{
char path[512] = { 0 };
unsigned int* v = (unsigned int*)&pid;
std::string ret("");
if (sizeof(pid) > 4 && v[1])
sprintf(path, "/proc/%lld/status", pid);
else
sprintf(path, "/proc/%u/status", pid);
FILE* src = fopen(path, "rb");
if (src)
{
char val[512] = { 0 };
memset(path, 0, sizeof(path));
fgets(path, sizeof(path) - 1, src);
fclose(src);
sscanf(path, "%*s %s", val);
ret = val;
}
if (sizeof(pid) > 4 && v[1])
{
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "PID(%lld) name is: %s\n", pid, ret.c_str());
2022-05-16 09:26:36 +00:00
}
else
{
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "PID(%u) name is: %s\n", pid, ret.c_str());
2022-05-16 09:26:36 +00:00
}
return ret;
}
#endif
2022-05-03 03:56:07 +00:00
bool shared_memory::is_ok(void)
{
return obj_ != nullptr;
}
bool shared_memory::is_first(void)
{
return is_ok() && first_;
}
std::string shared_memory::read(void)
{
if (obj_ == (void*)-1)
return "";
char* buf = get_buf();
if (buf == (char*)-1)
return "";
std::string ret("");
size_t len = 0;
int off = sizeof(size_t);
memcpy(&len, buf, off);
ret = std::string(buf + off, len);
release_buf(buf);
return ret;
}
int shared_memory::write(const char* data, size_t len)
{
if (len > bytes_)
return SCANNER_ERR_INSUFFICIENT_MEMORY;
2022-05-03 03:56:07 +00:00
char* buf = get_buf();
int off = sizeof(len);
if (buf == (char*)-1)
return errno;
memcpy(buf, &len, off);
memcpy(buf + off, data, len);
len_ = len;
release_buf(buf);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// tiny_file_map ...
tiny_file_map::tiny_file_map() : size_(0), map_(INVALID_HANDLE_NAME), buf_(nullptr), file_(""), keep_f_(false)
, map_off_(0), map_bytes_(0), page_size_(hg_log::get_page_size())
2022-06-16 08:03:55 +00:00
{
hg_log::get_page_size(&page_size_);
}
tiny_file_map::~tiny_file_map()
{
close();
}
HANDLE_NAME tiny_file_map::open_file_for_mapping(const char* file, unsigned* bytes, bool create)
{
HANDLE_NAME ret = INVALID_HANDLE_NAME;
#if defined(WIN32) || defined(_WIN64)
HANDLE f = INVALID_HANDLE_VALUE;
if (create)
{
f = CreateFileA(file, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (f != INVALID_HANDLE_VALUE)
{
DWORD wrote = SetFilePointer(f, *bytes - 1, NULL, FILE_BEGIN);
if (wrote != *bytes - 1 || !WriteFile(f, "\0", 1, &wrote, NULL))
{
CloseHandle(f);
f = INVALID_HANDLE_VALUE;
}
}
}
else
{
f = CreateFileA(file, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (f != INVALID_HANDLE_VALUE)
*bytes = GetFileSize(f, NULL);
}
if (f != INVALID_HANDLE_VALUE)
{
ret = CreateFileMapping(f, NULL, PAGE_READWRITE, 0, *bytes, NULL);
CloseHandle(f);
}
#else
if (create)
{
ret = ::open(file, O_CREAT | O_RDWR);
if (ret != INVALID_HANDLE_NAME)
{
if (lseek(ret, *bytes - 1, SEEK_SET) < 0)
{
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "set file size to %u - 1 bytes failed: %d\n", *bytes, errno);
::close(ret);
remove(file);
ret = INVALID_HANDLE_NAME;
}
if (write(ret, "0", 1) < 0)
{
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "set file size to %u bytes failed: %d\n", *bytes, errno);
::close(ret);
remove(file);
ret = INVALID_HANDLE_NAME;
}
}
}
else
{
ret = ::open(file, O_RDWR);
if (ret != INVALID_HANDLE_NAME)
{
struct stat fsize;
if (fstat(ret, &fsize) >= 0)
*bytes = fsize.st_size;
}
}
#endif
return ret;
}
void tiny_file_map::close_handle_name(HANDLE_NAME h)
{
#if defined(WIN32) || defined(_WIN64)
CloseHandle(h);
#else
::close(h);
#endif
}
void* tiny_file_map::sys_map_api(HANDLE_NAME h, int access, unsigned int off, unsigned size, int* err)
{
void* mem = nullptr;
#if defined(WIN32) || defined(_WIN64)
mem = MapViewOfFile(h, access, 0, off, size);
if (err)
{
if (mem)
*err = SCANNER_ERR_OK;
else
{
if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY)
*err = SCANNER_ERR_INSUFFICIENT_MEMORY;
else
*err = SCANNER_ERR_OUT_OF_RANGE;
}
}
#else
mem = mmap(nullptr, size, access, MAP_SHARED, h, off);
if (mem == MAP_FAILED)
{
mem = nullptr;
if (errno == ENOMEM)
*err = SCANNER_ERR_INSUFFICIENT_MEMORY;
else
*err = SCANNER_ERR_OUT_OF_RANGE;
}
else if(err)
*err = SCANNER_ERR_OK;
#endif
return mem;
}
void tiny_file_map::sys_unmap_api(void* buf, size_t size)
{
#if defined(WIN32) || defined(_WIN64)
UnmapViewOfFile(buf);
#else
munmap(buf, size);
#endif
}
int tiny_file_map::map_to_mem(unsigned int off)
{
int err = SCANNER_ERR_OUT_OF_RANGE;
#if defined(WIN32) || defined(_WIN64)
int acc = FILE_MAP_READ | FILE_MAP_WRITE;
#else
int acc = PROT_READ | PROT_WRITE;
#endif
if (off < size_)
{
unsigned int bytes = size_ - off;
if (off >= map_off_ && off + bytes <= map_off_ + map_bytes_)
err = SCANNER_ERR_OK;
else
{
if (buf_)
tiny_file_map::sys_unmap_api(buf_, map_bytes_);
off /= page_size_;
off *= page_size_;
map_bytes_ = bytes;
map_off_ = off;
buf_ = (unsigned char*)tiny_file_map::sys_map_api(map_, acc, map_off_, map_bytes_, &err); // MapViewOfFile(map_, FILE_MAP_READ | FILE_MAP_WRITE, 0, off, map_bytes_);
if (err != SCANNER_ERR_OK)
{
map_bytes_ /= page_size_;
map_bytes_ *= page_size_;
while (map_bytes_ >= page_size_
&& !(buf_ = (unsigned char*)tiny_file_map::sys_map_api(map_, acc, map_off_, map_bytes_, &err))
&& err == SCANNER_ERR_INSUFFICIENT_MEMORY)
map_bytes_ -= page_size_;
}
}
}
return err;
}
int tiny_file_map::open(const char* file, bool existing, unsigned int size)
{
int ret = SCANNER_ERR_INSUFFICIENT_MEMORY;
close();
map_ = tiny_file_map::open_file_for_mapping(file, &size, !existing);
if (map_ != INVALID_HANDLE_NAME)
{
ret = SCANNER_ERR_OK;
size_ = size;
}
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "map([%s]%s) = %d\n", existing ? "existing" : "new", file, ret);
if (ret == SCANNER_ERR_OK)
file_ = file;
return ret;
}
void tiny_file_map::close(void)
{
if (buf_)
{
tiny_file_map::sys_unmap_api(buf_, size_);
buf_ = nullptr;
}
if (map_ != INVALID_HANDLE_NAME)
{
close_handle_name(map_);
map_ = INVALID_HANDLE_NAME;
}
if (!keep_f_ && !file_.empty())
remove(file_.c_str());
size_ = 0;
file_ = "";
keep_f_ = false;
map_off_ = map_bytes_ = 0;
}
void tiny_file_map::keep_file(bool keep)
{
keep_f_ = keep;
}
unsigned char* tiny_file_map::mapping_buffer(unsigned int off, unsigned int* bytes)
{
unsigned int len = bytes ? *bytes : size_;
unsigned char* buf = nullptr;
if (off >= size_)
{
return buf;
}
if (!buf_ && map_to_mem(off) != SCANNER_ERR_OK)
{
return buf;
}
if (off >= map_off_ && off + len <= map_off_ + map_bytes_)
{
buf = buf_ + off - map_off_;
return buf;
}
if (off < map_off_ || off >= map_off_ + map_bytes_)
{
if (map_to_mem(off) == SCANNER_ERR_OK)
{
buf = buf_ + off - map_off_;
if (bytes)
*bytes = map_bytes_ - (off - map_off_);
}
return buf;
}
//
buf = buf_ + off - map_off_;
if (bytes)
*bytes = map_bytes_ - (off - map_off_);
return buf;
}
std::string tiny_file_map::file(void)
{
return file_;
}
unsigned int tiny_file_map::size(void)
{
return size_;
}
bool tiny_file_map::swap(void)
{
bool ret = true;
tiny_file_map::sys_unmap_api(buf_, size_);
buf_ = nullptr;
return ret;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// memory or file mapping ...
tiny_buffer::tiny_buffer(unsigned int size
, const char* tmp_path
, const char* name_leading
, const char* ext
, unsigned int uniq_id)
: size_(size), buf_(nullptr)
{
init(tmp_path, name_leading, ext, uniq_id);
}
tiny_buffer::tiny_buffer(const char* src_file) : size_(0), buf_(nullptr)
{
fmap_.open(src_file);
size_ = fmap_.size();
unsigned int len = size_;
buf_ = fmap_.mapping_buffer(0, &len);
}
tiny_buffer::~tiny_buffer()
{
if (buf_)
{
if (fmap_.file().empty())
delete[] buf_;
else
fmap_.close();
}
}
void tiny_buffer::init(const char* tmp_path, const char* name_leading, const char* ext, unsigned int uniq_id)
{
try
{
buf_ = new unsigned char[size_];
memset(buf_, 0, size_);
}
catch (...)
{
if (tmp_path && *tmp_path)
{
std::string f(tmp_path);
char buf[128] = { 0 };
f += PATH_SEPARATOR;
f += name_leading ? name_leading : "mapf";
sprintf(buf, "_%05u.%s", uniq_id, ext ? ext : "tmp");
f += buf;
unsigned int bytes = size_;
2022-06-16 08:03:55 +00:00
fmap_.open(f.c_str(), false, size_);
buf_ = fmap_.mapping_buffer(0, &bytes);
}
}
}
unsigned int tiny_buffer::size(void)
{
return size_;
}
unsigned char* tiny_buffer::data(unsigned int off, unsigned int* bytes)
{
if (off >= size_)
return nullptr;
if (fmap_.file().empty())
{
if (size_ - off < *bytes)
*bytes = size_ - off;
return buf_ + off;
}
return fmap_.mapping_buffer(off, bytes);
}
void tiny_buffer::keep_file(bool keep)
{
fmap_.keep_file(keep);
}
std::string tiny_buffer::file(void)
{
return fmap_.file();
}
bool tiny_buffer::swap(void)
{
if (fmap_.file().empty())
return true;
bool ret = fmap_.swap();
unsigned int bytes = size_;
buf_ = fmap_.mapping_buffer(0, &bytes);
return ret;
}
2022-07-19 09:12:06 +00:00
int tiny_buffer::to_file(const char* file)
{
FILE* dst = fopen(file, "wb");
if (!dst)
return errno;
2022-07-19 09:12:06 +00:00
unsigned int off = 0, len = size_;
unsigned char* buf = data(off, &len);
while (buf)
{
fwrite(buf, 1, len, dst);
off += len;
if (off >= size_)
break;
len = size_ - off;
buf = data(off, &len);
}
fclose(dst);
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// final_img_queue
final_img_queue::final_img_queue()
{}
final_img_queue::~final_img_queue()
{}
size_t final_img_queue::size(void)
{
std::lock_guard<std::mutex> lck(lock_);
return queue_.size();
}
void final_img_queue::clear(void)
{
std::lock_guard<std::mutex> lck(lock_);
queue_.clear();
}
bool final_img_queue::put(int w, int h, int bpp, int channels, int line_bytes, void* data, unsigned bytes
, const char* tmp_path, const char* name_leading, const char* ext, int ind)
{
IMGDT imgd;
bool ret = false;
unsigned int l = bytes, off = 0;
imgd.header.bits = bpp;
imgd.header.bytes = bytes;
imgd.header.channels = channels;
imgd.header.height = h;
imgd.header.line_bytes = line_bytes;
imgd.header.width = w;
imgd.offset = 0;
imgd.data.reset(new tiny_buffer(bytes, tmp_path, name_leading, ext, ind));
unsigned char* buf = imgd.data->data(off, &l),
* src = (unsigned char*)data;
while(buf)
{
memcpy(buf, src, l);
off += l;
if (off >= bytes)
break;
src += l;
l = bytes - off;
buf = imgd.data->data(off, &l);
}
if (off >= bytes && imgd.data->swap())
{
std::lock_guard<std::mutex> lck(lock_);
queue_.push_back(imgd);
ret = true;
}
else
imgd.data.reset();
return ret;
}
bool final_img_queue::front(IMH* header)
{
std::lock_guard<std::mutex> lck(lock_);
if (queue_.size() == 0)
return false;
memcpy(header, &queue_[0].header, sizeof(*header));
return true;
}
void final_img_queue::fetch_front(void* buf, int* len, bool* over)
{
std::lock_guard<std::mutex> lck(lock_);
if (queue_.size() == 0)
{
if(len)
*len = 0;
if(over)
*over = true;
}
else
{
// for third-apps, we make fake data upto len when re-map file failed here
IMGDT& imgd = queue_[0];
if (imgd.offset == 0)
{
if (!imgd.data->swap())
{
VLOG_MINI_1(LOG_LEVEL_FATAL, "Reload final image '%s' failed!\n", imgd.data->file().c_str());
}
}
if (imgd.offset + *len >= imgd.header.bytes)
*len = imgd.header.bytes - imgd.offset;
unsigned char* src = imgd.data->data(imgd.offset, (unsigned int*)len);
if (src)
{
memcpy(buf, src, *len);
}
else
{
VLOG_MINI_2(LOG_LEVEL_FATAL, "Remap final image '%s + 0x%08x' failed!\n", imgd.data->file().c_str(), imgd.offset);
}
imgd.offset += *len;
if (imgd.offset >= imgd.header.bytes)
{
if (over)
*over = true;
queue_.erase(queue_.begin());
}
}
}