- Reestructuración de ficheros y directorios general
- merge v0.01 --> Añadido fileselector - Añadidas fuentes de Gem y Pure Data - pix2jpg incluído en Gem. Archivos de construcción de Gem modificados. - Añadido fichero ompiling.txt con instrucciones de compilación
This commit is contained in:
parent
c9adfd020b
commit
e85d191b46
3100 changed files with 775434 additions and 3073 deletions
39
Gem/plugins/videoUNICAP/Makefile.am
Normal file
39
Gem/plugins/videoUNICAP/Makefile.am
Normal file
|
@ -0,0 +1,39 @@
|
|||
|
||||
ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src @GEM_EXTERNAL_CPPFLAGS@
|
||||
|
||||
pkglib_LTLIBRARIES=
|
||||
gemhelpdir=$(pkglibdir)
|
||||
dist_gemhelp_DATA =
|
||||
|
||||
if HAVE_LIB_LIBUNICAP
|
||||
pkglib_LTLIBRARIES+= gem_videoUNICAP.la
|
||||
dist_gemhelp_DATA +=unicap-videoplugin.pd
|
||||
endif
|
||||
|
||||
gem_videoUNICAP_la_CXXFLAGS =
|
||||
gem_videoUNICAP_la_LDFLAGS = -module -avoid-version -shared
|
||||
if WINDOWS
|
||||
gem_videoUNICAP_la_LDFLAGS += -no-undefined
|
||||
endif
|
||||
gem_videoUNICAP_la_LIBADD =
|
||||
|
||||
# RTE
|
||||
gem_videoUNICAP_la_CXXFLAGS += @GEM_RTE_CFLAGS@ @GEM_ARCH_CXXFLAGS@
|
||||
gem_videoUNICAP_la_LDFLAGS += @GEM_RTE_LIBS@ @GEM_ARCH_LDFLAGS@
|
||||
# flags for building Gem externals
|
||||
gem_videoUNICAP_la_CXXFLAGS += @GEM_EXTERNAL_CFLAGS@
|
||||
gem_videoUNICAP_la_LIBADD += -L$(top_builddir) @GEM_EXTERNAL_LIBS@
|
||||
# gem_videoUNICAP_la @MOREFLAGS@
|
||||
|
||||
# Dependencies
|
||||
gem_videoUNICAP_la_CXXFLAGS += @GEM_LIB_LIBUNICAP_CFLAGS@
|
||||
gem_videoUNICAP_la_LIBADD += @GEM_LIB_LIBUNICAP_LIBS@
|
||||
|
||||
# convenience symlinks
|
||||
include $(srcdir)/../symlink_ltlib.mk
|
||||
|
||||
|
||||
### SOURCES
|
||||
gem_videoUNICAP_la_SOURCES= videoUNICAP.cpp videoUNICAP.h
|
||||
|
2
Gem/plugins/videoUNICAP/unicap-videoplugin.pd
Normal file
2
Gem/plugins/videoUNICAP/unicap-videoplugin.pd
Normal file
|
@ -0,0 +1,2 @@
|
|||
#N canvas 8 49 505 112 10;
|
||||
#X text 89 47 Nothing special about this backend...;
|
778
Gem/plugins/videoUNICAP/videoUNICAP.cpp
Normal file
778
Gem/plugins/videoUNICAP/videoUNICAP.cpp
Normal file
|
@ -0,0 +1,778 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 2001-2012 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#if defined HAVE_LIBUNICAP && !defined HAVE_UNICAP
|
||||
# define HAVE_UNICAP
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_UNICAP
|
||||
|
||||
#include "videoUNICAP.h"
|
||||
#include "plugins/PluginFactory.h"
|
||||
|
||||
using namespace gem::plugins;
|
||||
|
||||
// for debugging...
|
||||
#include "Gem/RTE.h"
|
||||
|
||||
/* debugging helpers */
|
||||
#define debugPost
|
||||
#define debugThread
|
||||
|
||||
#if 0
|
||||
# undef debugPost
|
||||
# define debugPost ::startpost("%s:%s[%d]", __FILE__, __FUNCTION__, __LINE__), ::post
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
# undef debugThread
|
||||
# define debugThread ::startpost("%s:%s[%d]", __FILE__, __FUNCTION__, __LINE__), ::post
|
||||
#endif
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// videoUNICAP
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
REGISTER_VIDEOFACTORY("unicap", videoUNICAP);
|
||||
|
||||
|
||||
namespace {
|
||||
static const std::string s_name = std::string("unicap");
|
||||
}
|
||||
|
||||
videoUNICAP :: videoUNICAP(void) :
|
||||
m_width(-1), m_height(-1),
|
||||
m_handle(NULL),
|
||||
m_devicenum(-1),
|
||||
m_reqFormat(GL_RGBA_GEM),
|
||||
m_running(false)
|
||||
{
|
||||
enumerate();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
videoUNICAP :: ~videoUNICAP(void)
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
//////////////////
|
||||
// this reads the data that was captured by capturing() and returns it within a pixBlock
|
||||
pixBlock *videoUNICAP :: getFrame(void) {
|
||||
mutex.lock();
|
||||
return &m_pix;
|
||||
}
|
||||
|
||||
void videoUNICAP::releaseFrame(void) {
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
bool videoUNICAP :: open(gem::Properties&props) {
|
||||
std::vector<unsigned int>ds;
|
||||
if(m_devicename.empty()) {
|
||||
if(m_devicenum>=0)
|
||||
ds.push_back(m_devicenum);
|
||||
else
|
||||
ds.push_back(0);
|
||||
} else {
|
||||
ds=m_name2devices[m_devicename];
|
||||
}
|
||||
unicap_status_t status = -1;
|
||||
int i=0;
|
||||
for(i=0; i<ds.size(); i++) {
|
||||
unicap_device_t device;
|
||||
unsigned int d=ds[i];
|
||||
status = unicap_enumerate_devices (NULL, &device, d); // (1)
|
||||
if(SUCCESS(status)) {
|
||||
status = unicap_open (&m_handle, &device);
|
||||
if(SUCCESS(status)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!SUCCESS(status))
|
||||
return false;
|
||||
|
||||
setProperties(props);
|
||||
return true;
|
||||
}
|
||||
void videoUNICAP :: close(void) {
|
||||
if(m_handle) {
|
||||
unicap_close(m_handle);
|
||||
m_handle=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void videoUNICAP::newFrameCB (unicap_event_t event,
|
||||
unicap_handle_t handle,
|
||||
unicap_data_buffer_t * buffer,
|
||||
void *usr_data)
|
||||
{
|
||||
videoUNICAP*v=(videoUNICAP*)usr_data;
|
||||
debugPost("newFrameCB");
|
||||
if(v && UNICAP_EVENT_NEW_FRAME==event)
|
||||
v->newFrame(handle, buffer);
|
||||
}
|
||||
|
||||
namespace {
|
||||
typedef enum {
|
||||
FIRST=0,
|
||||
RGB,
|
||||
RGBA,
|
||||
BGR,
|
||||
BGRA,
|
||||
RGB16,
|
||||
ABGR,
|
||||
ARGB,
|
||||
GREY,
|
||||
GREY16,
|
||||
UYVY,
|
||||
YUY2,
|
||||
YVYU,
|
||||
YV12,
|
||||
YU12,
|
||||
|
||||
ILLEGAL
|
||||
} fourcc_t;
|
||||
|
||||
#ifdef FOURCC
|
||||
# undef FOURCC
|
||||
#endif
|
||||
|
||||
|
||||
#define FOURCC(a,b,c,d) (unsigned int)((((unsigned int)d)<<24)+(((unsigned int)c)<<16)+(((unsigned int)b)<<8)+a)
|
||||
/*
|
||||
#define FOURCC(a) (unsigned int) (
|
||||
((((unsigned char*)a)[0])<<24)+ \
|
||||
((((unsigned char*)a)[1])<<16)+ \
|
||||
((((unsigned char*)a)[2])<< 8)+ \
|
||||
((((unsigned char*)a)[3])<< 0))
|
||||
*/
|
||||
|
||||
static void post_fmt(unicap_format_t*fmt) {
|
||||
if(!fmt)return;
|
||||
const char*buftype="unknown";
|
||||
if(UNICAP_BUFFER_TYPE_USER==fmt->buffer_type)buftype="USER";
|
||||
if(UNICAP_BUFFER_TYPE_SYSTEM==fmt->buffer_type)buftype="SYSTEM";
|
||||
|
||||
debugPost("format '%s': ((%dx%d+%d+%d)) < (%dx%d+%d+%d) < ((%dx%d+%d+%d)) in +%d+%d steps\n"
|
||||
"\t%d sizes\n"
|
||||
"\tbuffers: %d types, %d systembuffers, %d size, type=%s"
|
||||
"",
|
||||
fmt->identifier,
|
||||
fmt->min_size.width, fmt->min_size.height,fmt->min_size.x, fmt->min_size.y,
|
||||
fmt->size.width, fmt->size.height,fmt->size.x, fmt->size.y,
|
||||
fmt->max_size.width, fmt->max_size.height,fmt->max_size.x, fmt->max_size.y,
|
||||
fmt->h_stepping, fmt->v_stepping,
|
||||
|
||||
fmt->size_count,
|
||||
|
||||
fmt->buffer_types, fmt->system_buffer_count, fmt->buffer_size, buftype,
|
||||
0);
|
||||
}
|
||||
|
||||
fourcc_t fourcc2fmt(unsigned int fourcc) {
|
||||
fourcc_t format=ILLEGAL;
|
||||
switch(fourcc) {
|
||||
default: format=ILLEGAL; break;
|
||||
|
||||
case (FOURCC('R', 'G', 'B', '2')): format=RGB; break;
|
||||
case (FOURCC('R', 'G', 'B', ' ')): format=RGB; break;
|
||||
case (FOURCC('R', 'G', 'B', 'A')): format=RGBA; break;
|
||||
case (FOURCC('B', 'G', 'R', ' ')): format=BGR; break;
|
||||
case (FOURCC('B', 'G', 'R', 'A')): format=BGRA; break;
|
||||
case (FOURCC('A', 'B', 'G', 'R')): format=ABGR; break;
|
||||
case (FOURCC('A', 'R', 'G', 'B')): format=ARGB; break;
|
||||
|
||||
case (FOURCC('Y', '8', '0', '0')):
|
||||
case (FOURCC('Y', ' ', ' ', ' ')):
|
||||
case (FOURCC('G', 'R', 'E', 'Y')): format=GREY; break;
|
||||
case (FOURCC('Y', '1', '6', ' ')): format=GREY16; break;
|
||||
|
||||
case (FOURCC('U', 'Y', 'N', 'V')):
|
||||
case (FOURCC('Y', '4', '2', '2')):
|
||||
case (FOURCC('H', 'D', 'Y', 'C')): // ?
|
||||
case (FOURCC('U', 'Y', 'V', 'Y')): format=UYVY; break;
|
||||
|
||||
case (FOURCC('Y', 'U', 'Y', 'V')):
|
||||
case (FOURCC('Y', 'U', 'N', 'V')):
|
||||
case (FOURCC('Y', 'U', 'Y', '2')): format=YUY2; break;
|
||||
|
||||
case (FOURCC('Y', 'V', 'Y', 'U')): format=YVYU; break;
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
float dimension_penalty(int w, int h, unicap_rect_t&size) {
|
||||
if(w>0 && h>0) {
|
||||
if(1) {
|
||||
// compare diagonals (penalty for very stretched formats
|
||||
double r=sqrt(w*w+h*h);
|
||||
double r0=sqrt(size.width*size.width+size.height*size.height);
|
||||
return fabs(r-r0);
|
||||
} else {
|
||||
// compare area
|
||||
double r=sqrt(w*h);
|
||||
double r0=sqrt(size.width*size.height);
|
||||
return fabs(r-r0);
|
||||
}
|
||||
} else if (w>0) {
|
||||
return fabs(w-size.width);
|
||||
} else if (h>0) {
|
||||
return fabs(h-size.height);
|
||||
}
|
||||
return 0.;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
void videoUNICAP::newFrame (unicap_handle_t handle,
|
||||
unicap_data_buffer_t * buffer) {
|
||||
unicap_format_t*fmt=&(buffer->format);
|
||||
post_fmt(fmt);
|
||||
fourcc_t format=fourcc2fmt(fmt->fourcc);
|
||||
|
||||
if(ILLEGAL==format) {
|
||||
verbose(1, "unsupported format '%s'", fmt->identifier);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char*data=buffer->data;
|
||||
debugPost("data: %p", data);
|
||||
|
||||
mutex.lock();
|
||||
m_pix.image.xsize=fmt->size.width;
|
||||
m_pix.image.ysize=fmt->size.height;
|
||||
|
||||
m_pix.image.upsidedown=true;
|
||||
|
||||
m_pix.image.reallocate(); // actually this is also done in from*()
|
||||
switch (format) {
|
||||
case RGB: m_pix.image.fromRGB(data); break;
|
||||
case RGBA: m_pix.image.fromRGBA(data); break;
|
||||
case BGR: m_pix.image.fromBGR(data); break;
|
||||
case BGRA: m_pix.image.fromBGRA(data); break;
|
||||
case RGB16: m_pix.image.fromRGB16(data); break;
|
||||
case ABGR: m_pix.image.fromABGR(data); break;
|
||||
case ARGB: m_pix.image.fromARGB(data); break;
|
||||
case GREY: m_pix.image.fromGray(data); break;
|
||||
case GREY16: m_pix.image.fromGray((short*)data); break;
|
||||
case UYVY: m_pix.image.fromUYVY(data); break;
|
||||
case YUY2: m_pix.image.fromYUY2(data); break;
|
||||
case YVYU: m_pix.image.fromYVYU(data); break;
|
||||
case YV12: m_pix.image.fromYV12(data); break;
|
||||
case YU12: m_pix.image.fromYU12(data); break;
|
||||
default:
|
||||
verbose(1, "cannot convert from given format");
|
||||
break;
|
||||
}
|
||||
m_pix.newimage=1;
|
||||
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// startTransfer
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
bool videoUNICAP :: start(void)
|
||||
{
|
||||
if(m_running)stop();
|
||||
unicap_status_t status = 0;
|
||||
unicap_format_t format;
|
||||
// defaultFormat();
|
||||
unicap_format_t format_spec;
|
||||
unicap_void_format( &format_spec );
|
||||
|
||||
int default_format=0 ;
|
||||
int default_size=0;
|
||||
|
||||
unsigned int count_format=0;
|
||||
|
||||
std::string s;
|
||||
if(m_props.get("format", s)) {
|
||||
for( unsigned i = 0; SUCCESS( unicap_enumerate_formats( m_handle, NULL, &format, i ) ); i++) {
|
||||
count_format++;
|
||||
if(s == format.identifier) {
|
||||
default_format=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int>formatid;
|
||||
if(default_format>=0) {
|
||||
formatid.push_back(default_format);
|
||||
} else {
|
||||
for(int i=0; i<count_format; i++) {
|
||||
formatid.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
int w=-1;
|
||||
int h=-1;
|
||||
double d;
|
||||
if(m_props.get("width" , d) && d>0)w=d;
|
||||
if(m_props.get("height", d) && d>0)h=d;
|
||||
|
||||
double penalty=-1.;
|
||||
debugPost("dimensions: %dx%d\t%f", w, h, penalty);
|
||||
if ((w>0 || h>0)) {
|
||||
/* try to find a format that matches the desired width/height best */
|
||||
for(unsigned int formatid_index=0; formatid_index<formatid.size(); formatid_index++) {
|
||||
int format_index=formatid[formatid_index];
|
||||
if( !SUCCESS( unicap_enumerate_formats( m_handle, &format_spec, &format, format_index) ) ) {
|
||||
post("Failed to get video format %d", format_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If a video format has more than one size, try to find the best match */
|
||||
if(format.size_count) {
|
||||
if(penalty<0) {
|
||||
penalty=dimension_penalty(w, h, format.sizes[0]);
|
||||
default_format=format_index;
|
||||
default_size=0;
|
||||
}
|
||||
debugPost("current penalty=%f", penalty);
|
||||
for( unsigned size_index = 0; size_index < format.size_count; size_index++ ) {
|
||||
double p=dimension_penalty(w, h, format.sizes[size_index]);
|
||||
debugPost("[%d/%d] penalty for (%dx%d) vs (%dx%d)=%f <> %f", format_index, size_index,
|
||||
w, h, format.sizes[size_index].width, format.sizes[size_index].height,
|
||||
p, penalty);
|
||||
if(p<penalty) { penalty=p;
|
||||
default_format=format_index;
|
||||
default_size=size_index;
|
||||
debugPost("new champion format=%d\tsize=%d", default_format, default_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unicap_void_format( &format_spec );
|
||||
if( !SUCCESS( unicap_enumerate_formats( m_handle, &format_spec, &format, default_format) ) ) {
|
||||
return false;
|
||||
}
|
||||
post_fmt(&format);
|
||||
|
||||
if(default_size>format.size_count) {
|
||||
debugPost("oops: want size #%d of %d", default_size, format.size_count);
|
||||
default_size=0;
|
||||
}
|
||||
format.size.width = format.sizes[default_size].width;
|
||||
format.size.height = format.sizes[default_size].height;
|
||||
|
||||
format.buffer_type = UNICAP_BUFFER_TYPE_SYSTEM;
|
||||
debugPost("setting format (%d/%d)", default_format, default_size);
|
||||
post_fmt(&format);
|
||||
if( !SUCCESS( unicap_set_format( m_handle, &format ) ) ) {
|
||||
verbose(1, "failed to set format");
|
||||
return false;
|
||||
}
|
||||
unicap_unregister_callback(m_handle, UNICAP_EVENT_NEW_FRAME);
|
||||
status=unicap_register_callback (m_handle,
|
||||
UNICAP_EVENT_NEW_FRAME,
|
||||
(unicap_callback_t) newFrameCB,
|
||||
(void *) this);
|
||||
debugPost("registered callback: %x", status);
|
||||
if(!SUCCESS(status)) {
|
||||
debugPost("callback miserably failed");
|
||||
return false;
|
||||
}
|
||||
status=unicap_start_capture (m_handle);
|
||||
debugPost("start capture: %x", status);
|
||||
if(!SUCCESS(status))
|
||||
return false;
|
||||
|
||||
m_running=true;
|
||||
return m_running;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// stopTransfer
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
bool videoUNICAP :: stop(void)
|
||||
{
|
||||
bool wasrunning=m_running;
|
||||
if(m_running)
|
||||
unicap_stop_capture (m_handle); // (3)
|
||||
|
||||
m_running=false;
|
||||
|
||||
return wasrunning;
|
||||
}
|
||||
|
||||
bool videoUNICAP :: reset(void) {
|
||||
#warning reset
|
||||
bool wasrunning=stop();
|
||||
close();
|
||||
enumerate();
|
||||
if(wasrunning) {
|
||||
open(m_props);
|
||||
start();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool videoUNICAP :: setColor(int format)
|
||||
{
|
||||
if (format<=0 || format==m_reqFormat)return false;
|
||||
m_reqFormat=format;
|
||||
// restartTransfer();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::string> videoUNICAP::enumerate(void) {
|
||||
std::vector<std::string> result;
|
||||
int devcount=0;
|
||||
unicap_status_t status = 0;
|
||||
int i=0;
|
||||
|
||||
m_providers.clear();
|
||||
m_providers.push_back(s_name);
|
||||
m_providers.push_back("analog");
|
||||
|
||||
|
||||
status = unicap_reenumerate_devices(&devcount);
|
||||
if(!SUCCESS(status))
|
||||
return result;
|
||||
|
||||
m_devices.clear();
|
||||
m_name2devices.clear();
|
||||
|
||||
|
||||
for(i=0; i<devcount; i++) {
|
||||
unicap_device_t device;
|
||||
status = unicap_enumerate_devices (NULL, &device, i); // (1)
|
||||
|
||||
|
||||
if(SUCCESS(status)) {
|
||||
const unsigned int cur=m_devices.size();
|
||||
#if 0
|
||||
post("ID='%s'\tmodel='%s'\tvendor='%s'\tdevice='%s'\tCPI='%s'",
|
||||
device.identifier,
|
||||
device.model_name,
|
||||
device.vendor_name,
|
||||
device.device,
|
||||
device.cpi_layer);
|
||||
#endif
|
||||
m_devices.push_back(device);
|
||||
|
||||
m_name2devices[device.identifier ].push_back(cur);
|
||||
m_name2devices[device.model_name ].push_back(cur);
|
||||
m_name2devices[device.vendor_name].push_back(cur);
|
||||
if(device.device[0])
|
||||
m_name2devices[device.device].push_back(cur);
|
||||
|
||||
/* hmm, think about this .... */
|
||||
std::string cpi=device.cpi_layer;
|
||||
cpi=cpi.substr(cpi.rfind("/")+1);
|
||||
cpi=cpi.substr(0, cpi.find("."));
|
||||
|
||||
provide(cpi);
|
||||
|
||||
result.push_back(device.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
bool videoUNICAP::setDevice(int ID) {
|
||||
m_devicename.clear();
|
||||
m_devicenum=ID;
|
||||
return true;
|
||||
}
|
||||
bool videoUNICAP::setDevice(const std::string ID) {
|
||||
m_devicename=ID;
|
||||
m_devicenum=-1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool videoUNICAP :: defaultFormat(void) {
|
||||
if(!m_handle)return false;
|
||||
int count=0;
|
||||
unicap_status_t status= unicap_reenumerate_formats(m_handle, &count );
|
||||
if(!SUCCESS(status))
|
||||
return false;
|
||||
|
||||
debugPost("got %d formats", count);
|
||||
if(count==0)return true;
|
||||
|
||||
unicap_format_t format;
|
||||
|
||||
for(int i=0; i<count; i++) {
|
||||
|
||||
status=unicap_enumerate_formats( m_handle, NULL, &format, i );
|
||||
|
||||
post_fmt(&format);
|
||||
|
||||
#if 0
|
||||
if(count==1) {
|
||||
|
||||
status= unicap_set_format(m_handle, &format);
|
||||
return SUCCESS(status);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool videoUNICAP :: enumProperties(gem::Properties&readable,
|
||||
gem::Properties&writeable) {
|
||||
readable.clear();
|
||||
writeable.clear();
|
||||
|
||||
if(m_handle) {
|
||||
int count=0;
|
||||
unicap_status_t status= unicap_reenumerate_properties(m_handle, &count );
|
||||
if(!SUCCESS(status))
|
||||
return false;
|
||||
|
||||
int id=0;
|
||||
for(id=0; id<count; id++) {
|
||||
unicap_property_t prop;
|
||||
gem::any typ;
|
||||
|
||||
status = unicap_enumerate_properties(m_handle, NULL, &prop, id);
|
||||
if(!SUCCESS(status))
|
||||
continue;
|
||||
|
||||
debugPost("id='%s'\tcat='%s'\tunit='%s'\tflags=%d",
|
||||
prop.identifier,
|
||||
prop.category,
|
||||
prop.unit,
|
||||
prop.flags);
|
||||
|
||||
|
||||
switch(prop.type) {
|
||||
case UNICAP_PROPERTY_TYPE_RANGE:
|
||||
debugPost("range %f-%f", prop.range.min, prop.range.min);
|
||||
typ=prop.range.max;
|
||||
break;
|
||||
case UNICAP_PROPERTY_TYPE_VALUE_LIST:
|
||||
debugPost("value_list %d", prop.value_list.value_count);
|
||||
typ=prop.value_list.value_count;
|
||||
break;
|
||||
case UNICAP_PROPERTY_TYPE_MENU:
|
||||
debugPost("menu '%s' of %d", prop.menu_item, prop.menu.menu_item_count);
|
||||
typ=std::string(prop.menu_item);//prop.menu.menu_item_count;
|
||||
break;
|
||||
case UNICAP_PROPERTY_TYPE_FLAGS:
|
||||
debugPost("flags");
|
||||
break;
|
||||
default:
|
||||
debugPost("unknown");
|
||||
// ?
|
||||
break;
|
||||
}
|
||||
|
||||
readable.set(prop.identifier, typ);
|
||||
if(!(prop.flags & UNICAP_FLAGS_READ_ONLY))
|
||||
writeable.set(prop.identifier, typ);
|
||||
|
||||
#warning check UNICAP_FLAGS_ON_OFF & UNICAP_FLAGS_ONE_PUSH
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void videoUNICAP :: getProperties(gem::Properties&props) {
|
||||
if(!m_handle)return;
|
||||
unicap_status_t status=0;
|
||||
|
||||
std::vector<std::string> keys=props.keys();
|
||||
|
||||
bool getwidth=false, getheight=false;
|
||||
int i=0;
|
||||
for(i=0; i<keys.size(); i++) {
|
||||
std::string key=keys[i];
|
||||
unicap_property_t prop;
|
||||
strncpy(prop.identifier, key.c_str(), 128);
|
||||
|
||||
if("width"==key) {
|
||||
getwidth=true;
|
||||
continue;
|
||||
}
|
||||
if("height"==key) {
|
||||
getheight=true;
|
||||
continue;
|
||||
}
|
||||
|
||||
status= unicap_get_property(m_handle, &prop );
|
||||
|
||||
if(SUCCESS(status)) {
|
||||
switch(prop.type) {
|
||||
case UNICAP_PROPERTY_TYPE_VALUE_LIST:
|
||||
case UNICAP_PROPERTY_TYPE_FLAGS:
|
||||
case UNICAP_PROPERTY_TYPE_RANGE:
|
||||
props.set(key, prop.value);
|
||||
break;
|
||||
case UNICAP_PROPERTY_TYPE_MENU:
|
||||
props.set(key, std::string(prop.menu_item));
|
||||
break;
|
||||
default:
|
||||
props.erase(key);
|
||||
// ?
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(getwidth||getheight) {
|
||||
unicap_format_t fmt;
|
||||
status=unicap_get_format(m_handle, &fmt);
|
||||
post("getting dimen");post_fmt(&fmt);
|
||||
if(SUCCESS(status)) {
|
||||
if(getwidth )props.set("width" , fmt.size.width);
|
||||
if(getheight)props.set("height", fmt.size.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
void videoUNICAP :: setProperties(gem::Properties&props) {
|
||||
m_props=props;
|
||||
debugPost("handle=%p", m_handle);
|
||||
if(!m_handle)
|
||||
return;
|
||||
|
||||
unicap_status_t status = 0;
|
||||
bool restart=false;
|
||||
|
||||
unsigned int width=0, height=0;
|
||||
|
||||
std::vector<std::string> keys=props.keys();
|
||||
int i=0;
|
||||
for(i=0; i<keys.size(); i++) {
|
||||
std::string key=keys[i];
|
||||
|
||||
double d=0;
|
||||
std::string s;
|
||||
|
||||
|
||||
if(("width"==key) && props.get(key, d)) {
|
||||
width=d;
|
||||
if(m_width!=width) {
|
||||
m_width=width;
|
||||
restart=true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(("height"==key) && props.get(key, d)) {
|
||||
height=d;
|
||||
if(m_height!=height) {
|
||||
m_height=height;
|
||||
restart=true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
unicap_property_t prop;
|
||||
strncpy(prop.identifier, key.c_str(), 128);
|
||||
status=unicap_get_property(m_handle, &prop );
|
||||
|
||||
if(SUCCESS(status)) {
|
||||
switch(prop.type) {
|
||||
case UNICAP_PROPERTY_TYPE_VALUE_LIST:
|
||||
case UNICAP_PROPERTY_TYPE_FLAGS:
|
||||
case UNICAP_PROPERTY_TYPE_RANGE:
|
||||
if(props.get(key, d)) {
|
||||
prop.value=d;
|
||||
status= unicap_set_property(m_handle, &prop );
|
||||
}
|
||||
break;
|
||||
case UNICAP_PROPERTY_TYPE_MENU:
|
||||
if(props.get(key, d)) {
|
||||
if(d>=0 && d < prop.menu.menu_item_count) {
|
||||
int i=d;
|
||||
/* unfortunately we must use the symbolic value and cannot simply set using the index... */
|
||||
strncpy(prop.menu_item, prop.menu.menu_items[i], 128);
|
||||
status= unicap_set_property(m_handle, &prop );
|
||||
}
|
||||
} else if (props.get(key, s)) {
|
||||
strncpy(prop.menu_item, s.c_str(), 128);
|
||||
status= unicap_set_property(m_handle, &prop );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// ?
|
||||
break;
|
||||
}
|
||||
|
||||
if(!SUCCESS(status)) {
|
||||
verbose(1, "could not set property '%s'", key.c_str());
|
||||
#if 0
|
||||
} else {
|
||||
verbose(1, "successfully set property '%s'", key.c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while(restart) { restart=false;
|
||||
debugPost("restarting stream due to property change");
|
||||
bool running=stop();
|
||||
debugPost("running=%d", running);
|
||||
if (running)start();
|
||||
}
|
||||
}
|
||||
|
||||
void videoUNICAP::provide(const std::string name) {
|
||||
if(!provides(name))
|
||||
m_providers.push_back(name);
|
||||
}
|
||||
|
||||
bool videoUNICAP::provides(const std::string name) {
|
||||
for(unsigned int i=0; i<m_providers.size(); i++) {
|
||||
if(name == m_providers[i])
|
||||
return true;
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
std::vector<std::string>videoUNICAP::provides(void) {
|
||||
std::vector<std::string>result;
|
||||
for(unsigned int i=0; i<m_providers.size(); i++) {
|
||||
result.push_back(m_providers[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
const std::string videoUNICAP::getName(void) {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
#endif /* HAVE_UNICAP */
|
132
Gem/plugins/videoUNICAP/videoUNICAP.h
Normal file
132
Gem/plugins/videoUNICAP/videoUNICAP.h
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*-----------------------------------------------------------------
|
||||
|
||||
GEM - Graphics Environment for Multimedia
|
||||
|
||||
capture an image using unicap
|
||||
|
||||
Copyright (c) 2001-2012 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
|
||||
For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
||||
WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INCLUDE_GEMPLUGIN__VIDEOUNICAP_VIDEOUNICAP_H_
|
||||
#define _INCLUDE_GEMPLUGIN__VIDEOUNICAP_VIDEOUNICAP_H_
|
||||
|
||||
#include "plugins/video.h"
|
||||
|
||||
#include "Gem/Image.h"
|
||||
#include "Gem/Properties.h"
|
||||
|
||||
#include <map>
|
||||
#define private unicap_private
|
||||
#include <unicap.h>
|
||||
#undef private
|
||||
#include "Utils/ThreadMutex.h"
|
||||
/*-----------------------------------------------------------------
|
||||
-------------------------------------------------------------------
|
||||
CLASS
|
||||
pix_video
|
||||
|
||||
grabs a video via UNICAP (http://unicap-imaging.org/)
|
||||
|
||||
KEYWORDS
|
||||
pix
|
||||
|
||||
-----------------------------------------------------------------*/
|
||||
namespace gem { namespace plugins {
|
||||
class GEM_EXPORT videoUNICAP : public video {
|
||||
public:
|
||||
//////////
|
||||
// Constructor
|
||||
videoUNICAP(void);
|
||||
|
||||
//////////
|
||||
// Destructor
|
||||
virtual ~videoUNICAP(void);
|
||||
|
||||
////////
|
||||
// open the video-device
|
||||
virtual bool open(gem::Properties&writeprops);
|
||||
virtual void close(void);
|
||||
|
||||
//////////
|
||||
// Start up the video device
|
||||
// [out] int - returns false if starting failed
|
||||
virtual bool start(void);
|
||||
//////////
|
||||
// Stop the video device
|
||||
// [out] int - returns 0 if bad
|
||||
virtual bool stop(void);
|
||||
|
||||
virtual bool reset(void);
|
||||
|
||||
//////////
|
||||
// get the next frame
|
||||
virtual pixBlock *getFrame(void);
|
||||
virtual void releaseFrame(void);
|
||||
|
||||
//////////
|
||||
// Set the video properties
|
||||
virtual bool setColor(int);
|
||||
|
||||
virtual bool defaultFormat(void);
|
||||
|
||||
virtual std::vector<std::string>enumerate(void);
|
||||
virtual bool setDevice(int ID);
|
||||
virtual bool setDevice(const std::string);
|
||||
|
||||
|
||||
virtual bool enumProperties(gem::Properties&readable,
|
||||
gem::Properties&writeable);
|
||||
virtual void setProperties(gem::Properties&writeprops);
|
||||
virtual void getProperties(gem::Properties&readprops);
|
||||
|
||||
virtual const std::string getName(void);
|
||||
|
||||
virtual std::vector<std::string>provides(void);
|
||||
virtual bool provides(const std::string);
|
||||
|
||||
virtual bool dialog(std::vector<std::string>) { return false; }
|
||||
virtual std::vector<std::string>dialogs(void) { std::vector<std::string>result; return result; }
|
||||
virtual bool isThreadable(void) { return false; }
|
||||
virtual bool grabAsynchronous(bool) { return false; }
|
||||
|
||||
protected:
|
||||
// list of backends we provide:
|
||||
std::vector<std::string>m_providers;
|
||||
virtual void provide(const std::string);
|
||||
|
||||
std::vector<unicap_device_t>m_devices;
|
||||
std::map<std::string, std::vector<unsigned int> >m_name2devices;
|
||||
|
||||
|
||||
unsigned int m_width, m_height;
|
||||
unicap_handle_t m_handle;
|
||||
|
||||
pixBlock m_pix;
|
||||
std::string m_devicename;
|
||||
int m_devicenum;
|
||||
|
||||
int m_reqFormat;
|
||||
|
||||
void newFrame (unicap_handle_t handle,
|
||||
unicap_data_buffer_t * buffer);
|
||||
|
||||
gem::thread::Mutex mutex;
|
||||
gem::Properties m_props;
|
||||
|
||||
private:
|
||||
static void newFrameCB (unicap_event_t event,
|
||||
unicap_handle_t handle,
|
||||
unicap_data_buffer_t * buffer,
|
||||
void *usr_data);
|
||||
|
||||
/* are we currently rendering? */
|
||||
bool m_running;
|
||||
|
||||
};
|
||||
};};
|
||||
|
||||
#endif // for header file
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue