unicap layer enhancements

also parameters implemented
still wondering why the eeepc cam doesn't works
it used to work... mmm...
This commit is contained in:
Jaromil
2009-04-08 20:34:33 +02:00
parent f9210067da
commit fb65e9ca59
5 changed files with 202 additions and 72 deletions
+3 -3
View File
@@ -346,10 +346,10 @@ int main (int argc, char **argv) {
func("creating layer for file %s",pp);
lay = create_layer(freej, pp); // hey, this already init and open the layer !!
lay = freej->open(pp); // hey, this already init and open the layer !!
if(lay) {
lay->start();
freej->add_layer(lay);
freej.add_layer(lay);
lay->start();
lay->fps.set(fps);
if (startstate)
+1
View File
@@ -65,6 +65,7 @@ class Parameter : public Entry {
filter_param_f *filter_get_f;
filter_param_f *filter_set_f;
bool changed; ///< can be used externally by application caller
};
#endif
+16 -2
View File
@@ -26,6 +26,9 @@
#include <context.h>
#define UNICAP_SYSTEM_CAPTURE 1
#define UNICAP_USER_CAPTURE 2
class UnicapLayer: public Layer {
@@ -42,14 +45,25 @@ class UnicapLayer: public Layer {
void *feed_ready;
void *rgba[2];
int swap;
int detected;
int capture_type;
Linklist<Parameter> parameters;
private:
unicap_device_t m_device;
unicap_device_t m_device_spec;
unicap_handle_t m_handle;
unicap_data_buffer_t m_buffer;
unicap_format_t m_format;
unicap_property_t m_property;
unicap_property_t m_property_spec;
};
#endif
+4 -3
View File
@@ -49,6 +49,8 @@ Parameter::Parameter(Parameter::Type param_type)
error("parameter initialized with unknown type: %u", param_type);
}
changed = false;
type = param_type;
layer_set_f = NULL;
@@ -65,13 +67,11 @@ bool Parameter::set(void *val) {
////////////////////////////////////////
if(type == Parameter::NUMBER) {
func("set_parameter number");
*(float*)value = *(float*)val;
//////////////////////////////////////
} else if(type == Parameter::BOOL) {
func("set_parameter bool");
*(bool*)value = *(bool*)val;
// act("filter %s parameter %s set to: %e", name, param->name, (double*)value);
@@ -97,7 +97,8 @@ bool Parameter::set(void *val) {
error("attempt to set value for a parameter of unknown type: %u", type);
return false;
}
changed = true;
return true;
}
+178 -64
View File
@@ -1,5 +1,5 @@
/* FreeJ
* (c) Copyright 2008 Denis Roio aka jaromil <jaromil@dyne.org>
* (c) Copyright 2008 - 2009 Denis Roio <jaromil@dyne.org>
*
* This source code is free software; you can redistribute it and/or
* modify it under the terms of the GNU Public License as published
@@ -30,21 +30,21 @@
UnicapLayer::UnicapLayer()
:Layer() {
unicap_device_t device;
int i=0;
m_handle = NULL;
notice("Unicap layer initialized, devices detected:");
while( SUCCESS(unicap_enumerate_devices( NULL, &device, i++)))
act("%u - %s",i,device.identifier);
m_handle = NULL;
m_buffer.data = NULL;
swap = 0;
rgba[0] = NULL;
rgba[1] = NULL;
feed_ready = NULL;
set_name("CAM");
// change this to UNICAP_USER_CAPTURE
// to switch the way unicap captures..
capture_type = UNICAP_SYSTEM_CAPTURE;
}
UnicapLayer::~UnicapLayer() {
@@ -70,6 +70,7 @@ static void new_frame_yuyv_cb (unicap_event_t event, unicap_handle_t handle,
unicap_data_buffer_t * buffer, void *usr_data) {
UnicapLayer *lay = (UnicapLayer*)usr_data;
func("cam callback");
ccvt_yuyv_bgr32(lay->geo.w, lay->geo.h, buffer->data, lay->rgba[lay->swap]);
lay->feed_ready = lay->rgba[lay->swap];
@@ -81,30 +82,39 @@ bool UnicapLayer::open(const char *devfile) {
bool res = false;
int i = 0;
int fourcc, bpp;
unicap_device_t device;
unicap_format_t format, format_spec;
unicap_format_t format_spec;
Parameter *p;
if(!detected) {
error("no video devices found");
return(false);
}
while( unicap_enumerate_devices( NULL, &device, i++)
while( unicap_enumerate_devices( &m_device_spec, &m_device, i++)
== STATUS_SUCCESS) {
if(strcmp(devfile,device.device)==0) { // found
func("checking device match \"%s\" == \"%s\"", m_device.device, devfile);
m_device = device;
if(strcasecmp(devfile,m_device.device)==0) { // found
if( unicap_open(&m_handle, &m_device ) == STATUS_SUCCESS ) {
res = true;
break;
} else {
error("error opening device %s", m_device.identifier);
return(false);
}
}
} else continue;
}
if(!res) {
error("Unicap device %s is not found", m_device.identifier);
return(false);
error("Unicap device %s is not found", devfile);
return(false);
}
notice("Unicap device opened: %s",m_device.identifier);
act("available video formats:");
@@ -112,17 +122,20 @@ bool UnicapLayer::open(const char *devfile) {
i=0;
fourcc=0;
while(SUCCESS(unicap_enumerate_formats( m_handle, &format_spec, &format, i++))) {
act("%u - %s - 0x%x - %u bpp",i, format.identifier, format.fourcc, format.bpp);
switch(format.fourcc) {
while(SUCCESS(unicap_enumerate_formats( m_handle, &format_spec, &m_format, i++))) {
act("%u - %s - 0x%x - %u bpp",i, m_format.identifier, m_format.fourcc, m_format.bpp);
switch(m_format.fourcc) {
case 0x33524742: // BGR24
fourcc = format.fourcc;
fourcc = m_format.fourcc;
bpp = 24;
unicap_register_callback (m_handle,
UNICAP_EVENT_NEW_FRAME,
(unicap_callback_t) new_frame_bgr24_cb,
(void*)this);
if(capture_type==UNICAP_SYSTEM_CAPTURE) {
unicap_register_callback (m_handle,
UNICAP_EVENT_NEW_FRAME,
(unicap_callback_t) new_frame_bgr24_cb,
(void*)this);
func("registered conversion callback BGR24");
}
break;
/*
@@ -137,26 +150,28 @@ bool UnicapLayer::open(const char *devfile) {
case 0x56595559: // YUYV and equivalents
case 0x32595559:
if(!fourcc) {
fourcc = format.fourcc;
fourcc = m_format.fourcc;
if(capture_type==UNICAP_SYSTEM_CAPTURE) {
unicap_register_callback (m_handle,
UNICAP_EVENT_NEW_FRAME,
(unicap_callback_t) new_frame_yuyv_cb,
(void*)this);
func("registered conversion callback YUYV");
}
break;
case 0x30323449:
case 0x56555949:
if(!fourcc) {
fourcc = format.fourcc;
fourcc = m_format.fourcc;
if(capture_type==UNICAP_SYSTEM_CAPTURE) {
unicap_register_callback (m_handle,
UNICAP_EVENT_NEW_FRAME,
(unicap_callback_t) new_frame_yuyv_cb,
(void*)this);
func("registered conversion callback YUYV");
}
break;
default: break;
}
@@ -167,50 +182,111 @@ bool UnicapLayer::open(const char *devfile) {
fourcc = 0x56595559;
}
if( ! SUCCESS( unicap_get_format (m_handle, &format) ))
if( ! SUCCESS( unicap_get_format (m_handle, &m_format) ))
error("format get failed on capture device");
// list sizes
act("%u supported sizes:", format.size_count);
act("%u supported sizes:", m_format.size_count);
act("min %ux%u - max %ux%u - stepping %ux%u",
format.min_size.width, format.min_size.height,
format.max_size.width, format.max_size.height,
format.h_stepping, format.v_stepping);
for(i=0; i<format.size_count; i++)
m_format.min_size.width, m_format.min_size.height,
m_format.max_size.width, m_format.max_size.height,
m_format.h_stepping, m_format.v_stepping);
for(i=0; i<m_format.size_count; i++)
act("%u - %u x %u", i,
format.sizes[i].width, format.sizes[i].height);
m_format.sizes[i].width, m_format.sizes[i].height);
// TODO: choose closest available size
format.size.width = geo.w;
format.size.height = geo.h;
format.buffer_type = UNICAP_BUFFER_TYPE_SYSTEM;
format.fourcc = fourcc;
format.bpp = bpp;
m_format.size.width = geo.w;
m_format.size.height = geo.h;
act("initializing at %ux%u bpp:%u fourcc:0x%x",
format.size.width, format.size.height,
format.bpp, format.fourcc);
if(capture_type==UNICAP_SYSTEM_CAPTURE) {
m_format.buffer_type = UNICAP_BUFFER_TYPE_SYSTEM;
} else {
m_format.buffer_type = UNICAP_BUFFER_TYPE_USER;
}
if( ! SUCCESS( unicap_set_format(m_handle, &format) )) {
m_format.fourcc = fourcc;
m_format.bpp = bpp;
act("initializing at %ux%u bpp:%u fourcc:0x%x",
m_format.size.width, m_format.size.height,
m_format.bpp, m_format.fourcc);
if( ! SUCCESS( unicap_set_format(m_handle, &m_format) )) {
error("format setting failed on capture device");
error("maybe the size is not supported by this camera");
error("else report your model and format strings");
// unicap_close(m_handle);
// return(false);
return(false);
}
// allocate first yuv buffer for grabbing
m_buffer.data = (unsigned char*)jalloc(m_format.buffer_size);
m_buffer.buffer_size = m_format.buffer_size;
rgba[0] = jalloc(format.size.width * format.size.height * 4);
rgba[1] = jalloc(format.size.width * format.size.height * 4);
feed_ready = rgba[1];
// allocate 32bit buffer for YUV -> RGBA transform
rgba[0] = jalloc(m_format.size.width * m_format.size.height * 4);
// rgba[1] = jalloc(format.size.width * format.size.height * 4);
// feed_ready = rgba[0];
// properties
// Initialize a property specifier structure
unicap_void_property( &m_property_spec );
i=0;
while(SUCCESS(unicap_enumerate_properties( m_handle, &m_property_spec, &m_property, i++))) {
char tmp[512];
unicap_get_property(m_handle, &m_property);
sprintf(tmp,"%i - %s", i, m_property.identifier);
switch( m_property.type ) {
case UNICAP_PROPERTY_TYPE_RANGE:
case UNICAP_PROPERTY_TYPE_VALUE_LIST:
sprintf(tmp,"%s = %.2f", tmp, m_property.value );
p = new Parameter(Parameter::NUMBER);
p->set_name(m_property.identifier);
p->description = " ";
p->set((void*)&m_property.value);
parameters.append(p);
break;
case UNICAP_PROPERTY_TYPE_MENU:
sprintf(tmp,"%s = %s", tmp, m_property.menu_item );
break;
case UNICAP_PROPERTY_TYPE_FLAGS:
{
sprintf(tmp,"%s =",tmp);
unsigned int j;
const char *flags[] =
{ "MANUAL", "AUTO", "ONE_PUSH", "READ_OUT",
"ON_OFF", "READ_ONLY", "FORMAT_CHANGE" };
for( j = 0; j < ( sizeof( flags ) / sizeof( char* ) ); j++ ) {
if( ( (unsigned int)m_property.flags & ( 1<<j ) ) == ( 1<<j ) ) {
sprintf("%s %s",tmp, (char*)flags[j] );
}
}
}
break;
default: break;
}
act("%s",tmp);
}
act("%u capture device properties found", i-1);
if( ! SUCCESS( unicap_start_capture( m_handle ) ))
error("start capture failed on capture device");
else func("capture started for CAM layer");
set_name(m_device.device);
if(capture_type==UNICAP_USER_CAPTURE) {
unicap_queue_buffer(m_handle, & m_buffer);
}
// set_name(m_device.device);
opened = true;
return(res);
}
@@ -220,13 +296,48 @@ bool UnicapLayer::init(Context *freej) {
}
bool UnicapLayer::init(Context *freej, int width, int height) {
func("%s %ux%u",__PRETTY_FUNCTION__,width, height);
notice("Unicap layer initialized, devices detected:");
unicap_void_device( &m_device_spec );
detected = 0;
while( SUCCESS(unicap_enumerate_devices( &m_device_spec, &m_device, detected))) {
act("%u - %s",detected,m_device.identifier);
detected++;
}
_init(width, height);
return true;
}
void *UnicapLayer::feed() {
return feed_ready;
Parameter *p;
if(!opened) {
error("%s : no device opened");
return(NULL);
}
// func("%s",__PRETTY_FUNCTION__);
// update parameters that changed
p = parameters.begin();
while(p) {
if(p->changed)
unicap_set_property_value( m_handle, p->name, *(double*)p->value);
p->changed = false;
p = (Parameter*)p->next;
}
if(capture_type==UNICAP_USER_CAPTURE) {
unicap_data_buffer_t *res;
unicap_wait_buffer(m_handle,&res);
ccvt_yuyv_bgr32(geo.w, geo.h, res->data, rgba[0]);
unicap_queue_buffer(m_handle,res);
}
return rgba[0];
}
@@ -238,16 +349,19 @@ void UnicapLayer::close() {
if(unicap_is_stream_locked(&m_device))
unicap_unlock_stream(m_handle);
status = unicap_stop_capture(m_handle);
if( ! SUCCESS( status ) ) {
error("unicap reports error in stop_capture: 0x%x", status);
unicap_stop_capture(m_handle);
if(m_handle) {
status = unicap_stop_capture(m_handle);
if( ! SUCCESS( status ) ) {
error("unicap reports error in stop_capture: 0x%x", status);
unicap_stop_capture(m_handle);
}
unicap_close(m_handle);
}
unicap_close(m_handle);
jfree(rgba[0]);
jfree(rgba[1]);
if(m_buffer.data) jfree(m_buffer.data);
if(rgba[0]) jfree(rgba[0]);
// if(rgba[1]) jfree(rgba[1]);
opened = false;
}