From 27cca67ad441ea482fe5ded83fd9e846552cbbe0 Mon Sep 17 00:00:00 2001 From: "N.N." Date: Sun, 1 Jun 2008 15:39:16 +0000 Subject: P.i.D.i.P. 1.12.23 ( My Mum\'s Cam ) svn path=/trunk/externals/pidip/; revision=9958 --- CHANGES.LOG | 6 +- configure.ac | 9 +- doc/pdp_ieee1394l-help.pd | 24 ++ include/dv1394.h | 258 ++++++++++++++++++++++ include/pidip_config.h.in | 3 + modules/pdp_ieee1394l.c | 546 ++++++++++++++++++++++++++++++++++++++++++++++ system/pidip.c | 8 + 7 files changed, 851 insertions(+), 3 deletions(-) create mode 100755 doc/pdp_ieee1394l-help.pd create mode 100755 include/dv1394.h create mode 100755 modules/pdp_ieee1394l.c diff --git a/CHANGES.LOG b/CHANGES.LOG index db1fd92..d0b5286 100644 --- a/CHANGES.LOG +++ b/CHANGES.LOG @@ -1,7 +1,9 @@ 0.12.23 ( codename My Mum's Cam ) added pdp_v4l2 : video 4 linux 2 object - ( code template from pdp_v4l and xawtv ( v4l2 driver ), - thanks to Tom Schouten & Gerd Knorr ) + code template from pdp_v4l and xawtv ( v4l2 driver ), + thanks to Tom Schouten & Gerd Knorr + added pdp_ieee1394 : finally, the firewire camera object for linux + written by Lluis Gomez i Bigorda ( ) 0.12.22 ( codename Visual Junk ) added pdp_dot : matrix printer effect diff --git a/configure.ac b/configure.ac index 382189f..59db721 100644 --- a/configure.ac +++ b/configure.ac @@ -20,10 +20,11 @@ enable_ffmpeg=no enable_mpeg4ip=no enable_lcapture=no +echo $host # Check for DarwinPorts and/or Fink on Mac OS X/Darwin case "$host" in *-darwin* | *-macos10*) - PDP_CAPTURE_OBJECT="$PDP_CAPTURE_OBJECT pdp_ieee1394.o" + PDP_CAPTURE_OBJECT="pdp_ieee1394.o" if test -d /sw ; then # Fink PATH="/sw/bin:/sw/sbin:$PATH" @@ -235,6 +236,12 @@ AC_CHECK_HEADER(linux/videodev2.h, AC_DEFINE(HAVE_V4L2, 1, build pdp_v4l2), echo " linux/videodev2.h not found: not building pdp_v4l2") +AC_CHECK_HEADER(libdv/dv.h, + PDP_CAPTURE_OBJECT="$PDP_CAPTURE_OBJECT pdp_ieee1394l.o" + PDP_PIDIP_LIBS="-ldv $PDP_PIDIP_LIBS" + AC_DEFINE(HAVE_LIBDV, 1, build pdp_ieee1394 for linux), + echo " libdv/dv.h not found: not building pdp_ieee1394") + if test $enable_ffmpeg == yes; then diff --git a/doc/pdp_ieee1394l-help.pd b/doc/pdp_ieee1394l-help.pd new file mode 100755 index 0000000..ca0a5c4 --- /dev/null +++ b/doc/pdp_ieee1394l-help.pd @@ -0,0 +1,24 @@ +#N canvas 173 49 765 399 10; +#X msg 151 -366 open /dev/dv1394/0; +#X obj 92 -148 pdp_xv; +#X obj 42 -369 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X obj 42 -342 metro 40; +#X msg 194 -300 norm PAL; +#X msg 164 -337 close; +#X obj 91 -229 pdp_ieee1394; +#X text 185 -134 written by Lluis Gomez i Bigorda ( lluisgomez@hangar.org +); +#X text 186 -158 pdp_ieee1394 ( source pdp_ieee1394l.c ) : fire wire +capture object for linux; +#X text 264 -300 setting video standard; +#X msg 194 -277 norm SECAM; +#X msg 195 -253 norm NTSC; +#X connect 0 0 6 0; +#X connect 2 0 3 0; +#X connect 3 0 6 0; +#X connect 4 0 6 0; +#X connect 5 0 6 0; +#X connect 6 0 1 0; +#X connect 10 0 6 0; +#X connect 11 0 6 0; diff --git a/include/dv1394.h b/include/dv1394.h new file mode 100755 index 0000000..f928e4d --- /dev/null +++ b/include/dv1394.h @@ -0,0 +1,258 @@ +/* + * dv1394.h - DV input/output over IEEE 1394 on OHCI chips + * Copyright (C)2001 Daniel Maas + * receive, proc_fs by Dan Dennedy + * + * based on: + * video1394.h - driver for OHCI 1394 boards + * Copyright (C)1999,2000 Sebastien Rougeaux + * Peter Schlaile + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _DV_1394_H +#define _DV_1394_H + +#include +#include + +/* This is the public user-space interface. Try not to break it. */ + +#define DV1394_API_VERSION 0x20011127 + +/* ******************** + ** ** + ** DV1394 API ** + ** ** + ******************** + + There are two methods of operating the DV1394 DV output device. + + 1) + + The simplest is an interface based on write(): simply write + full DV frames of data to the device, and they will be transmitted + as quickly as possible. The FD may be set for non-blocking I/O, + in which case you can use select() or poll() to wait for output + buffer space. + + To set the DV output parameters (e.g. whether you want NTSC or PAL + video), use the DV1394_INIT ioctl, passing in the parameters you + want in a struct dv1394_init. + + Example 1: + To play a raw .DV file: cat foo.DV > /dev/dv1394 + (cat will use write() internally) + + Example 2: + static struct dv1394_init init = { + 0x63, (broadcast channel) + 4, (four-frame ringbuffer) + DV1394_NTSC, (send NTSC video) + 0, 0 (default empty packet rate) + } + + ioctl(fd, DV1394_INIT, &init); + + while(1) { + read( , buf, DV1394_NTSC_FRAME_SIZE ); + write( , buf, DV1394_NTSC_FRAME_SIZE ); + } + + 2) + + For more control over buffering, and to avoid unnecessary copies + of the DV data, you can use the more sophisticated the mmap() interface. + First, call the DV1394_INIT ioctl to specify your parameters, + including the number of frames in the ringbuffer. Then, calling mmap() + on the dv1394 device will give you direct access to the ringbuffer + from which the DV card reads your frame data. + + The ringbuffer is simply one large, contiguous region of memory + containing two or more frames of packed DV data. Each frame of DV data + is 120000 bytes (NTSC) or 144000 bytes (PAL). + + Fill one or more frames in the ringbuffer, then use the DV1394_SUBMIT_FRAMES + ioctl to begin I/O. You can use either the DV1394_WAIT_FRAMES ioctl + or select()/poll() to wait until the frames are transmitted. Next, you'll + need to call the DV1394_GET_STATUS ioctl to determine which ringbuffer + frames are clear (ready to be filled with new DV data). Finally, use + DV1394_SUBMIT_FRAMES again to send the new data to the DV output. + + + Example: here is what a four-frame ringbuffer might look like + during DV transmission: + + + frame 0 frame 1 frame 2 frame 3 + + *--------------------------------------* + | CLEAR | DV data | DV data | CLEAR | + *--------------------------------------* + + + transmission goes in this direction --->>> + + + The DV hardware is currently transmitting the data in frame 1. + Once frame 1 is finished, it will automatically transmit frame 2. + (if frame 2 finishes before frame 3 is submitted, the device + will continue to transmit frame 2, and will increase the dropped_frames + counter each time it repeats the transmission). + + + If you called DV1394_GET_STATUS at this instant, you would + receive the following values: + + n_frames = 4 + active_frame = 1 + first_clear_frame = 3 + n_clear_frames = 2 + + At this point, you should write new DV data into frame 3 and optionally + frame 0. Then call DV1394_SUBMIT_FRAMES to inform the device that + it may transmit the new frames. + +*/ + + +/* maximum number of frames in the ringbuffer */ +#define DV1394_MAX_FRAMES 32 + +/* number of *full* isochronous packets per DV frame */ +#define DV1394_NTSC_PACKETS_PER_FRAME 250 +#define DV1394_PAL_PACKETS_PER_FRAME 300 + +/* size of one frame's worth of DV data, in bytes */ +#define DV1394_NTSC_FRAME_SIZE (480 * DV1394_NTSC_PACKETS_PER_FRAME) +#define DV1394_PAL_FRAME_SIZE (480 * DV1394_PAL_PACKETS_PER_FRAME) + + +enum pal_or_ntsc { + DV1394_NTSC = 0, + DV1394_PAL +}; + + +/* this is the argument to DV1394_INIT */ +struct dv1394_init { + /* DV1394_API_VERSION */ + unsigned int api_version; + + /* isochronous transmission channel to use */ + unsigned int channel; + + /* number of frames in the ringbuffer. Must be at least 2 + and at most DV1394_MAX_FRAMES. */ + unsigned int n_frames; + + /* send/receive PAL or NTSC video format */ + enum pal_or_ntsc format; + + /* the following are used only for transmission */ + + /* set these to zero unless you want a + non-default empty packet rate (see below) */ + unsigned long cip_n; + unsigned long cip_d; + + /* set this to zero unless you want a + non-default SYT cycle offset (default = 3 cycles) */ + unsigned int syt_offset; +}; + +/* Q: What are cip_n and cip_d? */ + +/* + A: DV video streams do not utilize 100% of the potential bandwidth offered + by IEEE 1394 (FireWire). To achieve the correct rate of data transmission, + DV devices must periodically insert empty packets into the 1394 data stream. + Typically there is one empty packet per 14-16 data-carrying packets. + + Some DV devices will accept a wide range of empty packet rates, while others + require a precise rate. If the dv1394 driver produces empty packets at + a rate that your device does not accept, you may see ugly patterns on the + DV output, or even no output at all. + + The default empty packet insertion rate seems to work for many people; if + your DV output is stable, you can simply ignore this discussion. However, + we have exposed the empty packet rate as a parameter to support devices that + do not work with the default rate. + + The decision to insert an empty packet is made with a numerator/denominator + algorithm. Empty packets are produced at an average rate of CIP_N / CIP_D. + You can alter the empty packet rate by passing non-zero values for cip_n + and cip_d to the INIT ioctl. + + */ + +struct dv1394_status { + /* this embedded init struct returns the current dv1394 + parameters in use */ + struct dv1394_init init; + + /* the ringbuffer frame that is currently being + displayed. (-1 if the device is not transmitting anything) */ + int active_frame; + + /* index of the first buffer (ahead of active_frame) that + is ready to be filled with data */ + unsigned int first_clear_frame; + + /* how many buffers, including first_clear_buffer, are + ready to be filled with data */ + unsigned int n_clear_frames; + + /* how many times the DV output has underflowed + since the last call to DV1394_GET_STATUS */ + unsigned int dropped_frames; + + /* N.B. The dropped_frames counter is only a lower bound on the actual + number of dropped frames, with the special case that if dropped_frames + is zero, then it is guaranteed that NO frames have been dropped + since the last call to DV1394_GET_STATUS. + */ +}; + +/* Get the driver ready to transmit video. pass a struct dv1394_init* as + * the parameter (see below), or NULL to get default parameters */ +#define DV1394_INIT _IOW('#', 0x06, struct dv1394_init) + +/* Stop transmitting video and free the ringbuffer */ +#define DV1394_SHUTDOWN _IO ('#', 0x07) + +/* Submit N new frames to be transmitted, where the index of the first new + * frame is first_clear_buffer, and the index of the last new frame is + * (first_clear_buffer + N) % n_frames */ +#define DV1394_SUBMIT_FRAMES _IO ('#', 0x08) + +/* Block until N buffers are clear (pass N as the parameter) Because we + * re-transmit the last frame on underrun, there will at most be n_frames + * - 1 clear frames at any time */ +#define DV1394_WAIT_FRAMES _IO ('#', 0x09) + +/* Capture new frames that have been received, where the index of the + * first new frame is first_clear_buffer, and the index of the last new + * frame is (first_clear_buffer + N) % n_frames */ +#define DV1394_RECEIVE_FRAMES _IO ('#', 0x0a) + +/* Tell card to start receiving DMA */ +#define DV1394_START_RECEIVE _IO ('#', 0x0b) + +/* Pass a struct dv1394_status* as the parameter */ +#define DV1394_GET_STATUS _IOR('#', 0x0c, struct dv1394_status) + +#endif /* _DV_1394_H */ diff --git a/include/pidip_config.h.in b/include/pidip_config.h.in index b31c9ea..c45ad42 100644 --- a/include/pidip_config.h.in +++ b/include/pidip_config.h.in @@ -12,3 +12,6 @@ /* Define to 1 if you have video 4 linux 2 */ #undef HAVE_V4L2 + +/* Define to 1 if you have libdv for firewire camera */ +#undef HAVE_LIBDV diff --git a/modules/pdp_ieee1394l.c b/modules/pdp_ieee1394l.c new file mode 100755 index 0000000..bab80e6 --- /dev/null +++ b/modules/pdp_ieee1394l.c @@ -0,0 +1,546 @@ +/* + * Pure Data Packet module. + * Copyright (c) by 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. + * + */ + + +#include "pdp_config.h" +#include "pdp.h" +#include "pdp_llconv.h" +#include "pdp_imageproc.h" +#include +#include +#include +#include +#include +#include +#include /* getopt_long() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dv1394.h" +#include + +#define N_BUF 2 /*DV1394_MAX_FRAMES/4*/ +#define PAL 0 +#define NTSC 1 + + +typedef struct pdp_ieee1394_struct +{ + t_object x_obj; + + t_outlet *x_outlet0; + + int x_width; + int x_height; + + int dvfd; + unsigned char *videobuf; + unsigned char *decodedbuf; + bool x_frame_ready; + int x_frame, x_lastframe; + bool x_continue_thread; + pthread_t x_thread_id; + + int x_framesize; + unsigned char *x_mmapbuf; + + dv_decoder_t *x_decoder; + + bool x_haveVideo; + bool x_capturing; + bool x_norm; + char* x_devicename; + int x_devicenum; + +} t_pdp_ieee1394; + + + +static void +process_image (t_pdp_ieee1394 *x) +{ + + unsigned int w,h; + int object,length,pos,i,encoding; + t_pdp* header; + t_image* image; + short int * data; + + //fputc ('.', stdout); + //fflush (stdout); + + + + /* create new packet */ + w = x->x_width; + h = x->x_height; + + + object = pdp_packet_new_image(PDP_IMAGE_YV12, w, h); + header = pdp_packet_header(object); + image = pdp_packet_image_info(object); + + if (!header){ + post("pdp_v4l: ERROR: can't allocate packet"); + return; + } + + data = (short int *) pdp_packet_data(object); + + /* convert data to pdp packet */ + //pdp_llconv(x->decodedbuf, RIF_YVYU_P____U8, data, RIF_YVU__P411_S16, w, h); + pdp_llconv(x->decodedbuf, RIF_RGB__P____U8, data, RIF_YVU__P411_S16, w, h); // + + + pdp_packet_pass_if_valid(x->x_outlet0, &object); +} + +static int pdp_ieee1394_read_frame(t_pdp_ieee1394 *x) +{ + + if (!x->x_decoder)return 0; + if (!x->x_frame_ready) { + //x->x_image.newimage = 0; + } + else { + dv_parse_header(x->x_decoder, x->videobuf); + dv_parse_packs (x->x_decoder, x->videobuf); + if(dv_frame_changed(x->x_decoder)) { + int pitches[3] = {0,0,0}; + // pitches[0]=x_decoder->width*3; // rgb + // pitches[0]=x_decoder->width*((x_reqFormat==GL_RGBA)?3:2); + pitches[0]=x->x_decoder->width*3; + x->x_height=x->x_decoder->height; + x->x_width=x->x_decoder->width; + + /* decode the DV-data to something we can handle and that is similar to the wanted format */ + // dv_report_video_error(x_decoder, videobuf); // do we need this ? + // gosh, this(e_dv_color_rgb) is expansive:: the decoding is done in software only... + // dv_decode_full_frame(x_decoder, videobuf, ((x_reqFormat==GL_RGBA)?e_dv_color_rgb:e_dv_color_yuv), &decodedbuf, pitches); + dv_decode_full_frame(x->x_decoder, x->videobuf, e_dv_color_rgb, &x->decodedbuf, pitches); + + // post("sampling %d", x_decoder->sampling); + + /* convert the colour-space to the one we want */ + /* + * btw. shouldn't this be done in [pix_video] rather than here ? + * no because [pix_video] knows nothing about the possible colourspaces in here + */ + + // letting the library do the conversion to RGB and then doing the conversion to RGBA + // is really stupid. + // let's do it all ourselfes: + // if (x_reqFormat==GL_RGBA)x_image.image.fromRGB(decodedbuf); else + //x_image.image.fromYVYU(decodedbuf); + process_image (x); + + } + + x->x_frame_ready = false; + } + + return 1; +} + + +static void *pdp_ieee1394_thread(void *voidx) +{ + t_pdp_ieee1394 *x = ((t_pdp_ieee1394 *)voidx); + + int fd=x->dvfd; + int framesize = x->x_framesize; + struct dv1394_status dvst; + int n_frames = N_BUF; + unsigned char* mmapbuf = x->x_mmapbuf; + + /* this will hang if no ieee1394-device is present, what to do about it ??? */ + x->x_haveVideo=false; + if(ioctl(fd, DV1394_WAIT_FRAMES, 1)) { + perror("error: ioctl WAIT_FRAMES"); + x->x_capturing=false; return NULL; + } + if (ioctl(fd, DV1394_GET_STATUS, &dvst)) { + perror("ioctl GET_STATUS"); + x->x_capturing=false; return NULL; + } + x->x_haveVideo=true; + x->x_capturing=true; + + //fprintf(stderr,"aqui1"); + while(x->x_continue_thread){ + //fprintf(stderr,"aqui2"); + if(ioctl(fd, DV1394_WAIT_FRAMES, n_frames - 1)) { + perror("error: ioctl WAIT_FRAMES"); + x->x_capturing=false; return NULL; + } + if (ioctl(fd, DV1394_GET_STATUS, &dvst)) { + perror("ioctl GET_STATUS"); + x->x_capturing=false; return NULL; + } + //fprintf(stderr,"aqui3"); + /* + dvst.init + dvst.active_frame + dvst.first_clear_frame + dvst.n_clear_frames + dvst.dropped_frames + */ + if (dvst.dropped_frames > 0) { + verbose(1,"dv1394: dropped at least %d frames", dvst.dropped_frames); + } + /* + memcpy( g_current_frame->data, + (g_dv1394_map + (dvst.first_clear_frame * DV1394_PAL_FRAME_SIZE)), + DV1394_PAL_FRAME_SIZE ); + */ + x->videobuf = mmapbuf + (dvst.first_clear_frame * framesize); + + //post("thread %d\t%x %x", me->frame, me->tvfd, me->vmmap); + if (ioctl(fd, DV1394_RECEIVE_FRAMES, 1) < 0) { + perror("receiving..."); + } + x->x_lastframe=x->x_frame; + x->x_frame++; + x->x_frame%=N_BUF; + x->x_frame_ready = true; + } + x->x_capturing=false; + + //process_image (x, x->videobuf); + + return 0; +} + +static void +close_device (t_pdp_ieee1394 *x) +{ + if(x->x_mmapbuf!=NULL)munmap(x->x_mmapbuf, N_BUF*x->x_framesize); + if(x->dvfd>=0)close(x->dvfd); + x->x_haveVideo=false; + +} + + +static int +startTransfer (t_pdp_ieee1394 *x) +{ + //if ((x->dvfd=openDevice(format))<0){ + // verbose(1, "DV4L: closed"); + // return(0); + //} + //x->x_image.newimage=0; + //x->x_image.image.data=0; + //x->x_image.image.xsize=720; + //x->x_image.image.ysize=576; + //x->x_image.image.setCsizeByFormat(x->x_reqFormat); + //x->x_image.image.reallocate(); + x->videobuf=NULL; + + x->x_frame_ready = false; + + if(x->x_decoder!=NULL)dv_decoder_free(x->x_decoder); + if (!(x->x_decoder=dv_decoder_new(1, 1, 1))){ + //error("DV4L: unable to create DV-decoder...closing"); + close_device(x); + return(0); + } + //x->x_decoder->quality=x->x_quality; + x->x_decoder->quality = DV_QUALITY_BEST; + verbose(1, "DV4L: DV decoding quality %d ", x->x_decoder->quality); + //fprintf(stderr,"before"); + x->x_continue_thread = true; + pthread_create(&x->x_thread_id, 0, pdp_ieee1394_thread, x); + return 1; +} + +static int +stopTransfer (t_pdp_ieee1394 *x) +{ + /* close the dv4l device and dealloc buffer */ + /* terminate thread if there is one */ + x->x_continue_thread=false; + int i=0; + if(x->x_haveVideo){ + while(x->x_capturing){ + struct timeval sleep; + sleep.tv_sec=0; sleep.tv_usec=10; /* 10us */ + select(0,0,0,0,&sleep); + i++; + } + verbose(1, "DV4L: shutting down dv1394 after %d usec", i*10); + ioctl(x->dvfd, DV1394_SHUTDOWN); + } + close_device(x); + return(1); +} + + +static void pdp_ieee1394_close(t_pdp_ieee1394 *x) +{ + /* close the v4l device and dealloc buffer */ + + void *dummy; + //x->x_initialized = false; + /* terminate thread if there is one */ + if(x->x_continue_thread){ + x->x_continue_thread = 0; + pthread_join (x->x_thread_id, &dummy); + } + + + //stop_capturing (x); + + //uninit_device (x); + + close_device (x); + + if (-1 == close (x->dvfd)) + post ("close"); + + x->dvfd = -1; +} + + +static int pdp_ieee1394_open(t_pdp_ieee1394 *x, t_symbol *name) +{ + x->x_devicename = name->s_name; + + if(x->x_haveVideo){ + verbose(1, "Stream already going on. Doing some clean-up..."); + stopTransfer(x); + } + + /* + All of the errors in this method return -1 anyhow, so fd should be 0 to allow + successful open if everything goes ok. + + Ico Bukvic ico@vt.edu 2-18-07 + */ + int fd = 0; + struct dv1394_init init = { + DV1394_API_VERSION, // api version + 0x63, // isochronous transmission channel + N_BUF, // number of frames in ringbuffer + (x->x_norm==NTSC)?DV1394_NTSC:DV1394_PAL, // PAL or NTSC + //DV1394_PAL, // PAL or NTSC + 0, 0 , 0 // default packet rate + }; + + x->x_framesize=(x->x_norm==NTSC)?DV1394_NTSC_FRAME_SIZE:DV1394_PAL_FRAME_SIZE; + //x->x_framesize=DV1394_PAL_FRAME_SIZE; + + if(x->x_devicename){ + if ((fd = open(x->x_devicename, O_RDWR)) < 0) { + perror(x->x_devicename); + return -1; + } + } else { + signed char devnum=(x->x_devicenum<0)?0:(signed char)x->x_devicenum; + char buf[256]; + buf[255]=0;buf[32]=0;buf[33]=0; + if (devnum<0)devnum=0; + snprintf(buf, 32, "/dev/ieee1394/dv/host%d/%s/in", devnum, (x->x_norm==NTSC)?"NTSC":"PAL"); + //snprintf(buf, 32, "/dev/ieee1394/dv/host%d/%s/in", devnum, "PAL"); + if ((fd = open(buf, O_RDWR)) < 0) { + snprintf(buf, 32, "/dev/dv1394/%d", devnum); + if ((fd = open(buf, O_RDWR)) < 0) { + if ((fd=open("/dev/dv1394", O_RDWR)) < 0) { + perror(buf); + return -1; + } + } + } + } + if (ioctl(fd, DV1394_INIT, &init) < 0) { + perror("initializing"); + close(fd); + return -1; + } + + x->x_mmapbuf = (unsigned char *) mmap( NULL, N_BUF*x->x_framesize, + PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if(x->x_mmapbuf == MAP_FAILED) { + perror("mmap frame buffers"); + close(fd); + return -1; + } + + if(ioctl(fd, DV1394_START_RECEIVE, NULL)) { + perror("dv1394 START_RECEIVE ioctl"); + close(fd); + return -1; + } + /*Extra verbosity never hurt anyone... + + Ico Bukvic ico@vt.edu 2-18-07 + */ + post("DV4L: Successfully opened..."); + startTransfer(x); + x->dvfd=fd; + + return 1; + +} + + +static int pdp_ieee1394_norm(t_pdp_ieee1394 *x, t_symbol *s) +{ + int inorm = x->x_norm; + char* norm=s->s_name; + switch(norm[0]){ + case 'N': case 'n': + inorm=NTSC; + break; + case 'P': case 'p': + inorm=PAL; + break; + } + if (inorm==x->x_norm)return 0; + x->x_norm=inorm; + return 0; +} + + +static void pdp_ieee1394_bang(t_pdp_ieee1394 *x) +{ + + /* if initialized, grab a frame and output it */ + + + + /* convert data to pdp packet */ +/* + switch(x->x_v4l_palette){ + case VIDEO_PALETTE_YUV420P: + pdp_llconv(newimage, RIF_YUV__P411_U8, data, RIF_YVU__P411_S16, w, h); + break;*/ + + /* long live standards. v4l's rgb is in fact ogl's bgr */ +/* case VIDEO_PALETTE_RGB24: + pdp_llconv(newimage, RIF_BGR__P____U8, data, RIF_YVU__P411_S16, w, h); + break; + + case VIDEO_PALETTE_RGB32: + pdp_llconv(newimage, RIF_BGRA_P____U8, data, RIF_YVU__P411_S16, w, h); + break; + + case VIDEO_PALETTE_YUV422: + pdp_llconv(newimage, RIF_YUYV_P____U8, data, RIF_YVU__P411_S16, w, h); + break;*/ + + + /*default: + post("pdp_ieee1394: unsupported palette"); + break; + }*/ + +/* + if (PDP_IMAGE_YV12 == x->x_pdp_image_type){ + pixel_unpack_u8s16_y(&newimage[0], data, nbpixels>>3, x->x_state_data->gain); + pixel_unpack_u8s16_uv(&newimage[plane1], &data[plane2], nbpixels>>5, x->x_state_data->gain); + pixel_unpack_u8s16_uv(&newimage[plane2], &data[plane1], nbpixels>>5, x->x_state_data->gain); + } +*/ + //x->x_v4l_palette = VIDEO_PALETTE_YUV420P; + //x->x_v4l_palette = VIDEO_PALETTE_RGB24; + +/* + + else if(PDP_IMAGE_GREY == x->x_pdp_image_type){ + pixel_unpack_u8s16_y(&newimage[0], data, nbpixels>>3, x->x_state_data->gain); + } +*/ + //post("pdp_ieee1394: mark unused %d", object); + + /*pdp_packet_pass_if_valid(x->x_outlet0, &object);*/ + +} + + + +static void pdp_ieee1394_free(t_pdp_ieee1394 *x) +{ + //pdp_ieee1394_close(x); + if(x->x_haveVideo)stopTransfer(x); + //if(x->decodedbuf)delete[]decodedbuf; + if(x->x_decoder!=NULL)dv_decoder_free(x->x_decoder); +} + +t_class *pdp_ieee1394_class; + + + +void *pdp_ieee1394_new(t_symbol *vdef, t_symbol *format) +{ + t_pdp_ieee1394 *x = (t_pdp_ieee1394 *)pd_new(pdp_ieee1394_class); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + + //x->x_channel = 0;//0x63; + x->x_devicenum = 0; + x->x_norm = PAL; + x->x_decoder=NULL; + x->x_frame_ready=false; + x->x_width=720; + x->x_height=576; + x->x_framesize=DV1394_PAL_FRAME_SIZE; + //x->x_quality = DV_QUALITY_BEST; + //x->decodedbuf = new unsigned char[720*576*3]; + x->decodedbuf = malloc (720*576*3*sizeof(unsigned char)); + x->x_haveVideo=false; + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_ieee1394_setup(void) +{ + post( " pdp_ieee1394 : linux dv interface by Lluis Gomez i Bigorda (lluisgomez@hangar.org)" ); + + pdp_ieee1394_class = class_new(gensym("pdp_ieee1394"), (t_newmethod)pdp_ieee1394_new, + (t_method)pdp_ieee1394_free, sizeof(t_pdp_ieee1394), 0, A_DEFSYMBOL, A_DEFSYMBOL, A_NULL); + + + class_addmethod(pdp_ieee1394_class, (t_method)pdp_ieee1394_read_frame, gensym("bang"), A_NULL); + class_addmethod(pdp_ieee1394_class, (t_method)pdp_ieee1394_close, gensym("close"), A_NULL); + class_addmethod(pdp_ieee1394_class, (t_method)pdp_ieee1394_open, gensym("open"), A_SYMBOL, A_NULL); + class_addmethod(pdp_ieee1394_class, (t_method)pdp_ieee1394_norm, gensym("norm"), A_SYMBOL, A_NULL); + +} + +#ifdef __cplusplus +} +#endif diff --git a/system/pidip.c b/system/pidip.c index 181a33b..3e0479e 100644 --- a/system/pidip.c +++ b/system/pidip.c @@ -85,6 +85,10 @@ extern "C" void pdp_v4l2_setup(void); #endif +#ifdef HAVE_LIBDV + void pdp_ieee1394_setup(void); +#endif + #ifdef __APPLE__ void pdp_ieee1394_setup(void); #endif @@ -184,6 +188,10 @@ void pidip_setup(void){ pdp_v4l2_setup(); #endif +#ifdef HAVE_LIBDV + pdp_ieee1394_setup(); +#endif + #ifdef __APPLE__ pdp_ieee1394_setup(); #endif -- cgit v1.2.1