27#define PERROR(x) LERROR("In file " << JEVOIS_ENGINE_CONFIG_FILE << ':' << linenum << ": " << x) 
   38  if (ispython) 
return JEVOIS_MODULE_PATH "/" + vendor + 
'/' + modulename + 
'/' + modulename + 
".py";
 
   42  std::filesystem::path 
const stem = modulename + 
".so";
 
   45  for (
auto const & entry : std::filesystem::directory_iterator(dir))
 
   46    if (entry.path().stem() == stem)
 
   47      try { ver = std::max(ver, std::stoi(entry.path().extension().string().substr(1))); } 
 
   52    std::filesystem::path 
const latest = (dir / stem).
string() + 
'.' + std::to_string(ver);
 
   54    if (delete_old_versions)
 
   55      for (
auto const & entry : std::filesystem::directory_iterator(dir))
 
   56        if (entry.path().stem() == stem && entry.path() != latest)
 
   57          std::filesystem::remove(entry.path());
 
   59    return latest.string();
 
   62  return (dir / stem).string();
 
 
   68  if (ispython) 
return JEVOIS_MODULE_PATH "/" + vendor + 
'/' + modulename + 
'/' + modulename + 
".py";
 
   69  else return JEVOIS_MODULE_PATH "/" + vendor + 
'/' + modulename + 
'/' + modulename + 
".C";
 
 
  100  return float(1000000000U / interval) * 0.01F;
 
 
  106  return (
unsigned int)(10000000.0F / fps + 0.499F);
 
 
  113  return float(interval.denominator * 100U / interval.numerator) * 0.01F;
 
 
  119  return { 100U, (
unsigned int)(fps * 100.0F) };
 
 
  125  std::ostringstream ss;
 
  126  ss << 
jevois::fccstr(ofmt) << 
' ' << ow << 
'x' << oh << 
" @ " << ofps << 
"fps";
 
 
  133  std::ostringstream ss;
 
  134  ss << 
jevois::fccstr(cfmt) << 
' ' << cw << 
'x' << ch << 
" @ " << cfps << 
"fps";
 
 
  141  std::ostringstream ss;
 
  142  ss << 
jevois::fccstr(c2fmt) << 
' ' << c2w << 
'x' << c2h << 
" @ " << cfps << 
"fps";
 
 
  149  std::string ret = cstr();
 
  150  if (crop == jevois::CropType::CropScale) ret += 
" + " + c2str();
 
 
  157  std::ostringstream ss;
 
  159  ss << 
"OUT: " << ostr() << 
" CAM: " << cstr();
 
  160  if (crop == jevois::CropType::CropScale) ss << 
" CAM2: " << c2str();
 
  162  ss << 
" MOD: " << vendor << 
':' << modulename << 
' ' << (ispython ? 
"Python" : 
"C++");
 
 
  170  std::ostringstream ss;
 
  172  ss << modulename << (ispython ? 
" (Py)" : 
" (C++)");
 
  173  ss << 
" CAM: " << cstr();
 
  174  if (crop == jevois::CropType::CropScale) ss << 
" + " << c2str();
 
 
  182  std::ostringstream ss;
 
  184  ss << modulename << (ispython ? 
" (Py)" : 
" (C++)");
 
  185  ss << 
" CAM: " << cstr();
 
  186  if (crop == jevois::CropType::CropScale) ss << 
" + " << c2str();
 
  191  case 0: ss << 
", OUT: None (headless)"; 
break;
 
  192  default: ss << 
", OUT: " << ostr() << 
' ';
 
 
  201  return (ofmt == other.
ofmt && ow == other.
ow && oh == other.
oh && std::abs(ofps - other.
ofps) < 0.01F &&
 
  202          cfmt == other.
cfmt && cw == other.
cw && ch == other.
ch && std::abs(cfps - other.
cfps) < 0.01F &&
 
  203          crop == other.
crop &&
 
  204          (crop != jevois::CropType::CropScale ||
 
  205           (c2fmt == other.
c2fmt && c2w == other.
c2w && c2h == other.
c2h && std::abs(cfps - other.
cfps) < 0.01F)));
 
 
  211  return (hasSameSpecsAs(other) && wdr == other.
wdr && vendor == other.
vendor && modulename == other.
modulename &&
 
 
  220  if (m.
wdr != jevois::WDRtype::Linear)
 
  225  case jevois::CropType::Scale:
 
  227  case jevois::CropType::Crop:
 
  228    out << m.
crop << 
':'; 
break;
 
  229  case jevois::CropType::CropScale:
 
  241  int parse_relative_dim(std::string 
const & str, 
int c)
 
  243    if (str.empty()) 
throw std::range_error(
"Invalid empty output width");
 
  244    if (str[0] == 
'+') 
return c + std::stoi(str.substr(1));
 
  245    else if (str[0] == 
'-') 
return c - std::stoi(str.substr(1));
 
  246    return std::stoi(str);
 
  249  void parse_cam_format(std::string 
const & str, 
unsigned int & fmt, jevois::WDRtype & wdr, jevois::CropType & crop,
 
  250                        unsigned int & c2fmt, 
unsigned int & c2w, 
unsigned int & c2h)
 
  253    wdr = jevois::WDRtype::Linear;
 
  254    crop = jevois::CropType::Scale;
 
  259    if (tok.empty()) 
throw std::range_error(
"Empty camera format is not allowed");
 
  261    for (std::string & t : tok)
 
  264      try { wdr = jevois::from_string<jevois::WDRtype>(t); 
continue; } 
catch (...) { }
 
  268      if (ttok.empty()) 
throw std::range_error(
"Invalid empty camera format modifier: " + t);
 
  272        crop = jevois::from_string<jevois::CropType>(ttok[0]);
 
  276        case jevois::CropType::Crop: 
if (ttok.size() == 1) 
continue; 
break;
 
  277        case jevois::CropType::Scale: 
if (ttok.size() == 1) 
continue; 
break;
 
  278        case jevois::CropType::CropScale:
 
  279          if (ttok.size() == 4)
 
  282            c2w = std::stoi(ttok[2]);
 
  283            c2h = std::stoi(ttok[3]);
 
  289      throw std::range_error(
"Invalid camera format modifier [" + t +
 
  290                             "] - must be Linear|DOL or Crop|Scale|CropScale=FCC@WxH");
 
  298  std::string of, cf, ows, ohs;
 
  303  m.
ow = parse_relative_dim(ows, m.
cw);
 
  304  m.
oh = parse_relative_dim(ohs, m.
ch);
 
  317std::vector<jevois::VideoMapping> jevois::loadVideoMappings(jevois::CameraSensor s, 
size_t & defidx, 
bool checkso,
 
  322  return jevois::videoMappingsFromStream(s, ifs, defidx, checkso, hasgui);
 
  326std::vector<jevois::VideoMapping> jevois::videoMappingsFromStream(jevois::CameraSensor s, std::istream & is,
 
  327                                                                  size_t & defidx, 
bool checkso, 
bool hasgui)
 
  330  std::vector<jevois::VideoMapping> mappings;
 
  333  for (std::string line; std::getline(is, line); ++linenum)
 
  336    if (tok.empty()) 
continue; 
 
  337    if (tok.size() == 1 && tok[0].empty()) 
continue; 
 
  338    if (tok[0][0] == 
'#') 
continue; 
 
  339    if (tok.size() < 10) { 
PERROR(
"Found " << tok.size() << 
" tokens instead of >= 10 -- SKIPPING"); 
continue; }
 
  345      m.
ofps = std::stof(tok[3]);
 
  348      m.
cw = std::stoi(tok[5]);
 
  349      m.
ch = std::stoi(tok[6]);
 
  350      m.
cfps = std::stof(tok[7]);
 
  352      m.
ow = parse_relative_dim(tok[1], m.
cw);
 
  353      m.
oh = parse_relative_dim(tok[2], m.
ch);
 
  355    catch (std::exception 
const & e) { 
PERROR(
"Skipping entry because of parsing error: " << e.what()); 
continue; }
 
  356    catch (...) { 
PERROR(
"Skipping entry because of parsing errors"); 
continue; }
 
  371    { 
PERROR(
"Camera video format [" << m.
cstr() << 
"] not supported by sensor -- SKIPPING."); 
continue; }
 
  375    { 
PERROR(
"Graphical user interface not available or disabled -- SKIPPING"); 
continue; }
 
  380    { 
PERROR(
"GUI output only supported on JeVois-Pro -- SKIPPING"); 
continue; }
 
  382#ifndef JEVOIS_PLATFORM 
  384    if (m.
crop == jevois::CropType::CropScale || m.
crop == jevois::CropType::Crop)
 
  385    { 
PERROR(
"Crop or Crop+Scale camera input only supported on JeVois-Pro platform -- SKIPPING"); 
continue; }
 
  394        if (defmapping.
cfmt == 0) { defmapping = m; 
LINFO(
"Default in videomappings.cfg is " << m.
str()); }
 
  395        if (tok.size() > 11 && tok[11][0] != 
'#') 
PERROR(
"Extra garbage after 11th token ignored");
 
  397      else if (tok[10][0] != 
'#') 
PERROR(
"Extra garbage after 10th token ignored");
 
  400    mappings.push_back(m);
 
  405  std::sort(mappings.begin(), mappings.end(),
 
  409              if (a.ofmt < b.ofmt) return true;
 
  410              if (a.ofmt == b.ofmt) {
 
  411                if (a.ow > b.ow) return true;
 
  413                  if (a.oh > b.oh) return true;
 
  415                    if (a.ofps > b.ofps) return true;
 
  416                    if (std::abs(a.ofps - b.ofps) < 0.01F) {
 
  420                      if (a.ofmt != 0 && a.ofmt != JEVOISPRO_FMT_GUI)
 
  421                        PERROR(
"WARNING: Two modes have identical output format: " << a.ostr());
 
  424                      if (a.cfmt < b.cfmt) return true;
 
  425                      if (a.cfmt == b.cfmt) {
 
  426                        if (a.cw > b.cw) return true;
 
  428                          if (a.ch > b.ch) return true;
 
  430                            if (a.cfps > b.cfps) return true;
 
  445  if (checkso == 
false) { defidx = 0; 
return mappings; }
 
  448  if (mappings.empty() || mappings.back().ofmt == 0 || mappings.back().ofmt == 
JEVOISPRO_FMT_GUI)
 
  450    PERROR(
"No valid video mapping with UVC output found -- INSERTING A DEFAULT ONE");
 
  452    m.
ofmt = V4L2_PIX_FMT_YUYV; m.
ow = 640; m.
oh = 480; m.
ofps = 30.0F;
 
  453    m.
cfmt = V4L2_PIX_FMT_YUYV; m.
cw = 640; m.
ch = 480; m.
cfps = 30.0F;
 
  458    mappings.push_back(m);
 
  465  auto a = mappings.begin(), b = a + 1;
 
  466  while (b != mappings.end())
 
  469    if (a->isSameAs(*b)) { b = mappings.erase(b); 
continue; }
 
  471    else if (b->ofmt != 0 && b->ofmt != 
JEVOISPRO_FMT_GUI && a->ofmt == b->ofmt && a->ow == b->ow && a->oh == b->oh)
 
  473      if (std::abs(a->ofps - b->ofps) < 0.01F) b->ofps -= 1.0F; 
 
  474      else if (b->ofps > a->ofps) b->ofps = a->ofps - 1.0F; 
 
  481  if (defmapping.
cfmt == 0)
 
  483    LERROR(
"No default video mapping provided, using first one with UVC output");
 
  484    for (
size_t i = 0; i < mappings.size(); ++i) 
if (mappings[i].ofmt) { defidx = i; 
break; }
 
  490    for (
size_t i = 0; i < mappings.size(); ++i) 
if (mappings[i].isSameAs(defmapping)) { defidx = i; 
break; }
 
  497  unsigned int ofmt = ~0U, ow = ~0U, oh = ~0U, iformat = 0, iframe = 0;
 
  501    if (m.
ofmt != ofmt) { ofmt = m.
ofmt; ow = ~0U; oh = ~0U; ++iformat; iframe = 0; } 
 
  502    if (m.
ow != ow || m.
oh != oh) { ow = m.
ow; oh = m.
oh; ++iframe; } 
 
  512                                 float oframespersec)
 const 
  514  if (ofmt == oformat && ow == owidth && oh == oheight && (std::abs(ofps - oframespersec) < 0.1F)) 
return true;
 
 
  523  std::string sopa = sopath();
 
  524  std::ifstream testifs(sopa);
 
  525  if (testifs.is_open() == 
false)
 
  528    ispython = 
true; sopa = sopath();
 
  529    std::ifstream testifs2(sopa);
 
  530    if (testifs2.is_open() == 
false) 
throw std::runtime_error(
"Could not open module file " + sopa + 
"|.so");
 
 
#define JEVOIS_MODULE_PATH
Base path for modules.
#define JEVOIS_ENGINE_CONFIG_FILE
Location of the engine videomappings.cfg definition file.
#define JEVOISPRO_FMT_GUI
JeVois-Pro zero-copy display of camera input frame (to be used as output mode in VideoMapping)
bool sensorSupportsFormat(CameraSensor s, VideoMapping const &m)
Check whether a given resolution and frame rate is supported by a sensor.
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level.
#define LDEBUG(msg)
Convenience macro for users to print out console or syslog messages, DEBUG level.
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level.
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
unsigned int strfcc(std::string const &str)
Convert a JeVois video format string to V4L2 four-cc code (V4L2_PIX_FMT_...)
std::string fccstr(unsigned int fcc)
Convert a V4L2 four-cc code (V4L2_PIX_FMT_...) to a 4-char string.
std::vector< std::string > split(std::string const &input, std::string const ®ex="\\s+")
Split string into vector of tokens using a regex to specify what to split on; default regex splits by...
unsigned int v4l2ImageSize(unsigned int fcc, unsigned int width, unsigned int height)
Return the image size in bytes for a given V4L2_PIX_FMT_..., width, height.
Main namespace for all JeVois classes and functions.
Simple struct to hold video mapping definitions for the processing Engine.
WDRtype wdr
Type of wide-dynamic-range (WDR) to use, if sensor supports it.
static struct v4l2_fract fpsToV4l2(float fps)
Convert from fps to V4L2 interval.
unsigned int cfmt
camera pixel format
unsigned int ow
output width
unsigned int csize() const
Return the size in bytes of a camera image.
unsigned int c2fmt
When crop is CropScale, pixel format of the scaled images, otherwise 0.
static float v4l2ToFps(struct v4l2_fract const &interval)
Convert from V4L2 interval to fps.
static unsigned int fpsToUvc(float fps)
Convert from fps to USB/UVC interval.
std::string modinfopath() const
Return the full absolute path and file name of the module's modinfo.html file.
bool hasSameSpecsAs(VideoMapping const &other) const
Equality operator for specs but not vendor or module name.
unsigned int c2w
When crop is CropScale, width of the scaled images, otherwise 0.
CropType crop
Type of crop/scale to apply if camera size does not match sensor native.
std::string modulename
Name of the Module that will process this mapping.
unsigned int osize() const
Return the size in bytes of an output image.
std::string ostr() const
Convenience function to print out FCC WxH @ fps, for the output (UVC) format.
std::string cstr() const
Convenience function to print out FCC WxH @ fps, for the input (camera) format.
std::string str() const
Convenience function to print out the whole mapping in a human-friendly way.
std::string c2str() const
Convenience function to print out FCC WxH @ fps, for the scaled camera input format,...
std::string cstrall() const
Convenience function to print out FCC WxH @ fps plus possibly second stream, for the input (camera) f...
float cfps
camera frame rate in frames/sec
bool ispython
True if the module is written in Python; affects behavior of sopath() only.
std::string menustr2() const
Convenience function to print out the whole mapping in a human-friendly way to be used in a menu.
void setModuleType()
Determine whether module is C++ or python and set ispython flag accordingly.
unsigned int c2size() const
Return the size in bytes of a scaled camera image, if stream==RawAndScaled, otherwise 0.
std::string path() const
Return the full absolute path the module's directory.
unsigned int cw
camera width
float ofps
output frame rate in frames/sec
unsigned int c2h
When crop is CropScale, height of the scaled images, otherwise 0.
unsigned int ch
camera height
bool isSameAs(VideoMapping const &other) const
Equality operator for specs and also vendor or module name.
unsigned int oh
output height
unsigned int uvcformat
USB-UVC format number (1-based)
static float uvcToFps(unsigned int interval)
Convert from USB/UVC interval to fps.
unsigned int uvcframe
USB UVC frame number (1-based)
std::string srcpath() const
Return the full absolute path and file name of the module's .C or .py file.
std::string menustr() const
Convenience function to print out the whole mapping in a human-friendly way to be used in a menu.
std::string vendor
Module creator name, used as a directory to organize the modules.
std::string sopath(bool delete_old_versions=false) const
Return the full absolute path and file name of the module's .so or .py file.
bool match(unsigned int oformat, unsigned int owidth, unsigned int oheight, float oframespersec) const
Return true if this VideoMapping's output format is a match to the given output parameters.
std::string cmakepath() const
Return the full absolute path and file name of the module's CMakeLists.txt file.
unsigned int ofmt
output pixel format, or 0 for no output over USB