diff options
-rw-r--r-- | Makefile.in | 7 | ||||
-rw-r--r-- | configure.ac | 10 | ||||
-rw-r--r-- | doc/pdp_dc1394-help.pd | 16 | ||||
-rw-r--r-- | modules/Makefile.in | 2 | ||||
-rwxr-xr-x | modules/pdp_dc1394.c | 456 | ||||
-rw-r--r-- | system/pidip.c | 2 |
6 files changed, 489 insertions, 4 deletions
diff --git a/Makefile.in b/Makefile.in index 1041b8f..0e59869 100644 --- a/Makefile.in +++ b/Makefile.in @@ -6,6 +6,7 @@ PDP_PIDIP_LIBS = @PDP_PIDIP_LIBS@ IMLIB_CFLAGS = @IMLIB_CFLAGS@ IMLIB_LIBS = @IMLIB_LIBS@ THEORA_LIBS = @THEORA_LIBS@ +DC1394_LIBS = @DC1394_LIBS@ PDP_PIDIP_INCLUDES = @PDP_PIDIP_INCLUDES@ PDP_PIDIP_VERSION = @PDP_PIDIP_VERSION@ MPEG4IP_CFLAGS = @MPEG4IP_CFLAGS@ @@ -40,12 +41,12 @@ pdp_pidip_all: pidip.pd_darwin: pdp_pidip_all rm -f pidip.pd_darwin - g++ -bundle -undefined dynamic_lookup -headerpad_max_install_names -o pidip.pd_darwin modules/*.o system/*.o -L/sw/lib $(THEORA_LIBS) $(PDP_PIDIP_LIBS) $(IMLIB_LIBS) + g++ -bundle -undefined dynamic_lookup -headerpad_max_install_names -o pidip.pd_darwin modules/*.o system/*.o -L/sw/lib $(THEORA_LIBS) $(DC1394_LIBS) $(PDP_PIDIP_LIBS) $(IMLIB_LIBS) strip -x pidip.pd_darwin pidip.pd_linux: pdp_pidip_all - rm -f pidip.pd_linux - g++ -Wl,--export-dynamic -shared -o pidip.pd_linux modules/*.o system/*.o $(THEORA_LIBS) $(PDP_PIDIP_LIBS) $(IMLIB_LIBS) + rm -f pidip.pd_linu + g++ -export_dynamic -shared -o pidip.pd_linux modules/*.o system/*.o $(THEORA_LIBS) $(PDP_PIDIP_LIBS) $(IMLIB_LIBS) $(DC1394_LIBS) strip --strip-unneeded pidip.pd_linux clean: diff --git a/configure.ac b/configure.ac index 76af1fe..15c293a 100644 --- a/configure.ac +++ b/configure.ac @@ -11,11 +11,13 @@ FFMPEG_SOURCE_DIR=/SOURCES/ffmpeg MPEG4IP_SOURCE_DIR=/SOURCES/mpeg4ip PDP_STREAMING_OBJECTS= PDP_CAPTURE_OBJECT= +PDP_DC1394_OBJECT IMLIB_LIBS= IMLIB_CFLAGS= MAGIC_LIBS= MAGIC_CFLAGS= THEORA_LIBS= +DC1394_LIBS= enable_ffmpeg=no enable_mpeg4ip=no enable_lcapture=no @@ -130,6 +132,11 @@ AC_CHECK_LIB(Magick, XWindowByProperty, echo "Image Magick not found : not building pdp_capture", -I/usr/X11R6/include -L/usr/X11R6/lib ) +AC_CHECK_LIB(dc1394, dc1394_camera_enumerate, + [ PDP_DC1394_OBJECT="pdp_dc1394.o" + DC1394_LIBS="-ldc1394 -lraw1394"], + echo "dc1394 not found : not building pdp_dc1394", ) + AC_CHECK_LIB(bz2, BZ2_bzBuffToBuffCompress, , AC_MSG_ERROR(streaming requires bz2 library!!)) AC_CHECK_LIB(z, deflate, , AC_MSG_ERROR(streaming requires compress library!!)) AC_CHECK_LIB(dl, dlopen, , AC_MSG_ERROR(streaming requires dynamic loader library!!)) @@ -139,6 +146,7 @@ AC_CHECK_LIB(vorbis, vorbis_analysis_init, , AC_MSG_ERROR(streaming requires vor AC_CHECK_LIB(vorbisenc, vorbis_encode_setup_init, , AC_MSG_ERROR(streaming requires vorbis encoder library!!), -lm) AC_CHECK_LIB(theora, theora_encode_init, , AC_MSG_ERROR(theora library needed! sorry...), -lm) AC_CHECK_LIB(quicktime, lqt_decode_video, , AC_MSG_ERROR(libquicktime not found) ) +AC_CHECK_LIB(dc1394, dc1394_camera_enumerate, , AC_MSG_ERROR(dc1394 not found) ) qt_minor_version="`lqt-config --version | cut -f3 -d'.'`" qt_major_version="`lqt-config --version | cut -f1 -d'.'`" @@ -286,8 +294,10 @@ AC_SUBST(PDP_PIDIP_VERSION) AC_SUBST(IMLIB_LIBS) AC_SUBST(IMLIB_CFLAGS) AC_SUBST(THEORA_LIBS) +AC_SUBST(DC1394_LIBS) AC_SUBST(PDP_STREAMING_OBJECTS) AC_SUBST(PDP_CAPTURE_OBJECT) +AC_SUBST(PDP_DC1394_OBJECT) AC_SUBST(PDP_PIDIP_LIBS) AC_SUBST(PDP_PIDIP_INCLUDES) diff --git a/doc/pdp_dc1394-help.pd b/doc/pdp_dc1394-help.pd new file mode 100644 index 0000000..8f1b4c8 --- /dev/null +++ b/doc/pdp_dc1394-help.pd @@ -0,0 +1,16 @@ +#N canvas 0 0 1039 352 10; +#X obj -81 101 pdp_dc1394; +#X obj -79 50 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 +-1; +#X obj -81 177 pdp_xv; +#X obj -18 57 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X obj 5 73 metro 20; +#X text 141 24 pdp_dc1394 is a first implementation of using DC1394 +cameras in pdp. For now its only tested with a Monochrome camera but +there is lot of work to do :: handling errors \, adding control messages +and to suport other colorspaces.; +#X connect 0 0 2 0; +#X connect 1 0 0 0; +#X connect 3 0 4 0; +#X connect 4 0 0 0; diff --git a/modules/Makefile.in b/modules/Makefile.in index 5b3df36..4e408a5 100644 --- a/modules/Makefile.in +++ b/modules/Makefile.in @@ -21,6 +21,6 @@ OBJECTS = pdp_intrusion.o pdp_yqt.o pdp_simura.o pdp_underwatch.o \ pdp_theorout~.o pdp_cropper.o pdp_background.o \ pdp_mapper.o pdp_theonice~.o pdp_icedthe~.o\ pdp_fdiff.o pdp_hue.o pdp_dot.o pdp_qtext.o\ - @PDP_CAPTURE_OBJECT@ @PDP_STREAMING_OBJECTS@ # pdp_xcanvas.o pdp_aa.o + @PDP_CAPTURE_OBJECT@ @PDP_STREAMING_OBJECTS@ @PDP_DC1394_OBJECT@ # pdp_xcanvas.o pdp_aa.o all_modules: $(OBJECTS) diff --git a/modules/pdp_dc1394.c b/modules/pdp_dc1394.c new file mode 100755 index 0000000..6930fe6 --- /dev/null +++ b/modules/pdp_dc1394.c @@ -0,0 +1,456 @@ +/* + * PiDiP module + * Authors : Yves Degoyon ( ydegoyon@free.fr ) and Lluis Gomez i Bigorda + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* This object is a video 4 linux 2 driver wrapper, + * inspired by pdp_v4l by Tom Schouten + * and some driver code from xawtv ( thanks to Gerd Knorr <kraxel@bytesex.org> ) + */ + + +#include "pdp_config.h" +#include "pdp.h" +#include "pdp_llconv.h" +#include "pdp_imageproc.h" +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/time.h> +#include <linux/types.h> +#include <sys/mman.h> +#include <sched.h> +#include <pthread.h> +#include <stdint.h> +#include <inttypes.h> +#include <dc1394/dc1394.h> + +// dont open any more after a set number +// of failed attempts +// this is to prevent locks on auto-open +// is reset when manually opened or closed +#define PDP_XV_RETRIES 10 + + +#define DEVICENO 0 +#define NBUF 2 +#define COMPOSITEIN 1 +#define WANTED_BUFFERS 2 +#define MAX_INPUT 16 +#define MAX_NORM 16 +#define MAX_FORMAT 32 +#define MAX_CTRL 32 + +#define IMAGE_FILE_NAME "image.pgm" +/*----------------------------------------------------------------------- + * Releases the cameras and exits + *-----------------------------------------------------------------------*/ +void cleanup_and_exit(dc1394camera_t *camera) +{ + dc1394_video_set_transmission(camera, DC1394_OFF); + dc1394_capture_stop(camera); + dc1394_camera_free(camera); + exit(1); +} + + + +typedef struct pdp_dc1394_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + + bool x_initialized; + bool x_auto_open; + + unsigned int x_width; + unsigned int x_height; + + int x_curinput; + int x_curstandard; + int x_curformat; + int x_freq; + + // video 4 linux 2 structures + int x_ninputs; + int x_nstandards; + int x_nformats; + + unsigned char *x_pdp_buf[WANTED_BUFFERS]; + + int x_tvfd; + int x_frame; + int x_skipnext; + int x_mytopmargin, x_mybottommargin; + int x_myleftmargin, x_myrightmargin; + + t_symbol *x_device; + + pthread_t x_thread_id; + int x_continue_thread; + int x_frame_ready; + int x_only_new_frames; + int x_last_frame; + + int x_open_retry; + + u32 x_minwidth; + u32 x_maxwidth; + u32 x_minheight; + u32 x_maxheight; + + int x_debug; + + + dc1394camera_t *camera; + int i; + dc1394featureset_t features; + dc1394framerates_t framerates; + dc1394video_modes_t video_modes; + dc1394framerate_t framerate; + dc1394video_mode_t video_mode; + dc1394color_coding_t coding; + unsigned int width, height; + dc1394video_frame_t *frame; + dc1394_t * d; + dc1394camera_list_t * list; + + dc1394error_t err; + +} t_pdp_dc1394; + +static void pdp_dc1394_close(t_pdp_dc1394 *x) +{ + +} + +static void pdp_dc1394_close_manual(t_pdp_dc1394 *x) +{ +} + +static void pdp_dc1394_close_error(t_pdp_dc1394 *x) +{ +} + +static int pdp_dc1394_capture_frame(t_pdp_dc1394* x) +{ + return 0; +} + +static void pdp_dc1394_wait_frame(t_pdp_dc1394* x) +{ +} + +static int pdp_dc1394_start_capturing(t_pdp_dc1394 *x) +{ + return 0; +} + +static int pdp_dc1394_stop_capturing(t_pdp_dc1394 *x) +{ + return 0; +} + +static void *pdp_dc1394_thread(void *voidx) +{ + return 0; +} + +static void pdp_dc1394_setlegaldim(t_pdp_dc1394 *x, int xx, int yy); + +static int pdp_dc1394_set_format(t_pdp_dc1394 *x, t_int index) +{ + return 0; +} + +static int pdp_dc1394_init_mmap(t_pdp_dc1394 *x) +{ + return 0; +} + +static void pdp_dc1394_open(t_pdp_dc1394 *x, t_symbol *name) +{ + +} + +static void pdp_dc1394_open_manual(t_pdp_dc1394 *x, t_symbol *name) +{ +} + + + +static void pdp_dc1394_standard(t_pdp_dc1394 *x, t_float f) +{ +} + +static void pdp_dc1394_format(t_pdp_dc1394 *x, t_float f) +{ +} + +static void pdp_dc1394_freq(t_pdp_dc1394 *x, t_float f) +{ +} + +static void pdp_dc1394_freqMHz(t_pdp_dc1394 *x, t_float f) +{ +} + + +static void pdp_dc1394_bang(t_pdp_dc1394 *x) +{ + + /* if initialized, grab a frame and output it */ + + unsigned int w,h,nbpixels,packet_size,plane1,plane2; + unsigned char *newimage=NULL; + int pdp_packt,length,pos,i,encoding; + t_pdp* header; + t_image* image; + unsigned char * data; + + static short int gain[4] = {0x7fff, 0x7fff, 0x7fff, 0x7fff}; + + /*----------------------------------------------------------------------- + * capture one frame + *-----------------------------------------------------------------------*/ + //x->err=dc1394_capture_dequeue(x->camera, DC1394_CAPTURE_POLICY_WAIT, &x->frame); + //DC1394_ERR_CLN_RTN(x->err,cleanup_and_exit(x->camera),"Could not capture a frame"); + //post("Could not capture a frame"); + if (x->err=dc1394_capture_dequeue(x->camera, DC1394_CAPTURE_POLICY_WAIT, &x->frame)!=DC1394_SUCCESS) { + post("Failed to capture from camera %d", x->err); + return; + } + + /* create new packet */ + dc1394_get_image_size_from_video_mode(x->camera, x->video_mode, &x->width, &x->height); + + pdp_packt = pdp_packet_new_bitmap_rgb(x->width, x->height); + header = pdp_packet_header(pdp_packt); + //image = pdp_packet_image_info(pdp_packt); + + if (!header){ + post("pdp_dc1394: ERROR: can't allocate packet"); + return; + } + + data = ( unsigned char *) pdp_packet_data(pdp_packt); + int j; + + for (i=0; i<x->width; i++) + for (j=0; j<x->height; j++) { + data[(j*x->width+i)*3] = x->frame->image[j*x->width+i]; + data[(j*x->width+i)*3+1] = x->frame->image[j*x->width+i]; + data[(j*x->width+i)*3+2] = x->frame->image[j*x->width+i]; + } + + //memcpy( data, x->frame->image, x->width*x->height*sizeof( unsigned char) ); + + /*FILE* imagefile=fopen(IMAGE_FILE_NAME, "wb"); + + if( imagefile == NULL) { + perror( "Can't create '" IMAGE_FILE_NAME "'"); + cleanup_and_exit(x->camera); + } + + fprintf(imagefile,"P5\n%u %u 255\n", x->width, x->height); + fwrite(x->frame->image, 1, x->height*x->width, imagefile); + fclose(imagefile); + fprintf(stderr,"wrote: " IMAGE_FILE_NAME "\n");*/ + + if (x->frame) + dc1394_capture_enqueue (x->camera, x->frame); + + pdp_packet_pass_if_valid(x->x_outlet0, &pdp_packt); + +} + + +static void pdp_dc1394_setlegaldim(t_pdp_dc1394 *x, int xx, int yy) +{ + + unsigned int w,h; + + w = pdp_imageproc_legalwidth((int)xx); + h = pdp_imageproc_legalheight((int)yy); + + w = (w < x->x_maxwidth) ? w : x->x_maxwidth; + w = (w > x->x_minwidth) ? w : x->x_minwidth; + + h = (h < x->x_maxheight) ? h : x->x_maxheight; + h = (h > x->x_minheight) ? h : x->x_minheight; + + x->x_width = w; + x->x_height = h; +} + +static void pdp_dc1394_dim(t_pdp_dc1394 *x, t_floatarg xx, t_floatarg yy) +{ + if (!x->x_initialized){ + post( "pdp_dc1394 : cannot set dim : no device opened "); + return; + } + if (x->x_initialized){ + pdp_dc1394_close(x); + pdp_dc1394_setlegaldim(x, (int)xx, (int)yy); + pdp_dc1394_open(x, x->x_device); + } +} + +static void pdp_dc1394_free(t_pdp_dc1394 *x) +{ + dc1394_video_set_transmission(x->camera, DC1394_OFF); + dc1394_capture_stop(x->camera); + dc1394_camera_free(x->camera); + dc1394_free (x->d); +} + +t_class *pdp_dc1394_class; + +void *pdp_dc1394_new(t_symbol *vdef) +{ + t_pdp_dc1394 *x = (t_pdp_dc1394 *)pd_new(pdp_dc1394_class); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + + x->d = dc1394_new (); + x->err=dc1394_camera_enumerate (x->d, &x->list); + //DC1394_ERR_RTN(x->err,"Failed to enumerate cameras"); + //post("Failed to enumerate cameras"); + + if (x->list->num == 0) { + dc1394_log_error("No cameras found"); + return 1; + } + + x->camera = dc1394_camera_new (x->d, x->list->ids[0].guid); + if (!x->camera) { + //dc1394_log_error("Failed to initialize camera with guid %"PRIx64, list->ids[0].guid); + return 1; + } + dc1394_camera_free_list (x->list); + + //printf("Using camera with GUID %"PRIx64"\n", camera->guid); + + /*----------------------------------------------------------------------- + * get the best video mode and highest framerate. This can be skipped + * if you already know which mode/framerate you want... + *-----------------------------------------------------------------------*/ + // get video modes: + x->err=dc1394_video_get_supported_modes(x->camera,&x->video_modes); + //DC1394_ERR_CLN_RTN(x->err,cleanup_and_exit(x->camera),"Can't get video modes"); + + // select highest res mode: + for (x->i=x->video_modes.num-1;x->i>=0;x->i--) { + if (!dc1394_is_video_mode_scalable(x->video_modes.modes[x->i])) { + dc1394_get_color_coding_from_video_mode(x->camera,x->video_modes.modes[x->i], &x->coding); + if (x->coding==DC1394_COLOR_CODING_MONO8) { + x->video_mode=x->video_modes.modes[x->i]; + fprintf(stderr,"video_mode %d: %d\n",x->i,x->video_modes.modes[x->i]); + break; + } + } + } + if (x->i < 0) { + dc1394_log_error("Could not get a valid MONO8 mode"); + cleanup_and_exit(x->camera); + } + + x->err=dc1394_get_color_coding_from_video_mode(x->camera, x->video_mode,&x->coding); + //DC1394_ERR_CLN_RTN(x->err,cleanup_and_exit(x->camera),"Could not get color coding"); + fprintf(stderr,"color_coding : %d\n",x->coding); + + // get highest framerate + x->err=dc1394_video_get_supported_framerates(x->camera,x->video_mode,&x->framerates); + //DC1394_ERR_CLN_RTN(x->err,cleanup_and_exit(x->camera),"Could not get framrates"); + x->framerate=x->framerates.framerates[x->framerates.num-1]; + fprintf(stderr,"framerate : %d\n",x->framerate); + + /*----------------------------------------------------------------------- + * setup capture + *-----------------------------------------------------------------------*/ + + x->err=dc1394_video_set_iso_speed(x->camera, DC1394_ISO_SPEED_400); + //DC1394_ERR_CLN_RTN(x->err,cleanup_and_exit(x->camera),"Could not set iso speed"); + + x->err=dc1394_video_set_mode(x->camera, x->video_mode); + //DC1394_ERR_CLN_RTN(x->err,cleanup_and_exit(x->camera),"Could not set video mode"); + + x->err=dc1394_video_set_framerate(x->camera, x->framerate); + //DC1394_ERR_CLN_RTN(x->err,cleanup_and_exit(x->camera),"Could not set framerate"); + + x->err=dc1394_capture_setup(x->camera,4, DC1394_CAPTURE_FLAGS_DEFAULT); + //DC1394_ERR_CLN_RTN(x->err,cleanup_and_exit(x->camera),"Could not setup camera-\nmake sure that the video mode and framerate are\nsupported by your camera"); + + /*----------------------------------------------------------------------- + * report camera's features + *-----------------------------------------------------------------------*/ + x->err=dc1394_feature_get_all(x->camera,&x->features); + if (x->err!=DC1394_SUCCESS) { + dc1394_log_warning("Could not get feature set"); + } + else { + dc1394_feature_print_all(&x->features, stdout); + } + + /*----------------------------------------------------------------------- + * have the camera start sending us data + *-----------------------------------------------------------------------*/ + x->err=dc1394_video_set_transmission(x->camera, DC1394_ON); + //DC1394_ERR_CLN_RTN(x->err,cleanup_and_exit(x->camera),"Could not start camera iso transmission"); + + + + x->x_initialized = true; + + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_dc1394_setup(void) +{ + pdp_dc1394_class = class_new(gensym("pdp_dc1394"), (t_newmethod)pdp_dc1394_new, + (t_method)pdp_dc1394_free, sizeof(t_pdp_dc1394), 0, A_DEFSYMBOL, A_DEFSYMBOL, A_NULL); + + class_addmethod(pdp_dc1394_class, (t_method)pdp_dc1394_close_manual, gensym("close"), A_NULL); + class_addmethod(pdp_dc1394_class, (t_method)pdp_dc1394_open_manual, gensym("open"), A_SYMBOL, A_NULL); + class_addmethod(pdp_dc1394_class, (t_method)pdp_dc1394_format, gensym("format"), A_FLOAT, A_NULL); + class_addmethod(pdp_dc1394_class, (t_method)pdp_dc1394_standard, gensym("standard"), A_FLOAT, A_NULL); + class_addmethod(pdp_dc1394_class, (t_method)pdp_dc1394_dim, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(pdp_dc1394_class, (t_method)pdp_dc1394_bang, gensym("bang"), A_NULL); + +} + +#ifdef __cplusplus +} +#endif diff --git a/system/pidip.c b/system/pidip.c index 78dec9c..c6514a2 100644 --- a/system/pidip.c +++ b/system/pidip.c @@ -80,6 +80,7 @@ extern "C" void pdp_fdiff_setup(void); void pdp_hue_setup(void); void pdp_dot_setup(void); + void pdp_dc1394_setup(void); #ifdef HAVE_V4L2 void pdp_v4l2_setup(void); @@ -183,6 +184,7 @@ void pidip_setup(void){ pdp_fdiff_setup(); pdp_hue_setup(); pdp_dot_setup(); + pdp_dc1394_setup(); #ifdef HAVE_V4L2 pdp_v4l2_setup(); |