From fe5ae89555ead1863420c1a9c389553e75e4527c Mon Sep 17 00:00:00 2001 From: "N.N." Date: Tue, 30 Mar 2004 02:59:55 +0000 Subject: New in PiDiP 0.12.13 svn path=/trunk/externals/pidip/; revision=1509 --- modules/pdp_ieee1394.c | 483 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 483 insertions(+) create mode 100644 modules/pdp_ieee1394.c (limited to 'modules/pdp_ieee1394.c') diff --git a/modules/pdp_ieee1394.c b/modules/pdp_ieee1394.c new file mode 100644 index 0000000..189398f --- /dev/null +++ b/modules/pdp_ieee1394.c @@ -0,0 +1,483 @@ +/* + * PiDiP module. + * Copyright (c) by Yves Degoyon (ydegoyon@free.fr) + * + * 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 ieee1394 video input object for OSX, using QuickTime + * Some code is inspired by pix_video from Gem + * Written by Yves Degoyon + */ + +#include "pdp_config.h" +#include "pdp.h" +#include "pdp_llconv.h" +#include "pdp_imageproc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_WIDTH 320 +#define DEFAULT_HEIGHT 240 + +typedef struct pdp_ieee1394_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + + bool x_initialized; + bool x_auto_open; + + t_int x_packet; + t_pdp* x_header; + short int *x_data; + unsigned char *x_sdata; // static data to hold the grabbed images + + unsigned int x_width; + unsigned int x_height; + unsigned int x_size; + int x_channel; + pthread_t x_thread_id; + int x_continue_thread; + unsigned int x_framerate; + int x_frame_ready; + t_int x_quality; + + SeqGrabComponent x_sg; + SGChannel x_vc; + short x_pixelDepth; + Rect x_srcRect; + GWorldPtr x_srcGWorld; + PixMapHandle x_pixMap; + Ptr x_baseAddr; + long x_rowBytes; + +} t_pdp_ieee1394; + +static void pdp_ieee1394_close(t_pdp_ieee1394 *x) +{ + void *dummy; + + /* terminate thread if there is one */ + if(x->x_continue_thread) + { + x->x_continue_thread = 0; + // pthread_join (x->x_thread_id, &dummy); + } + + // free sequence grabber + // if (x->x_vc) + // { + // if (SGDisposeChannel(x->x_sg, x->x_vc)) + // { + // post("pdp_ieee1394: unable to dispose video channel"); + // } + // x->x_vc = NULL; + // post("pdp_ieee1394: disposed video channel"); + // } + // if (x->x_sg) + // { + // if (CloseComponent(x->x_sg)) + // { + // post("pdp_ieee1394: unable to free sequence grabber."); + // } + // x->x_sg = NULL; + // post("pdp_ieee1394: freed sequence grabber."); + // } + // if (x->x_srcGWorld) + // { + // DisposeGWorld(x->x_srcGWorld); + // post("pdp_ieee1394: disposed world."); + // x->x_srcGWorld = NULL; + // } + +} + +static void pdp_ieee1394_capture_frame(t_pdp_ieee1394* x) +{ + OSErr err; + + err = SGIdle(x->x_sg); + if (err != noErr) + { + post("pdp_ieee1394: SGIdle failed."); + x->x_frame_ready = 0; + } + else + { + x->x_frame_ready = 1; + } +} + + +static void *pdp_ieee1394_thread(void *voidx) +{ + t_pdp_ieee1394 *x = ((t_pdp_ieee1394 *)voidx); + + /* capture with a double buffering scheme */ + while (true) + { + if (x->x_continue_thread) + { + /* schedule capture command for next frame */ + pdp_ieee1394_capture_frame(x); + } + else + { + sleep(1); + } + } + + x->x_thread_id = 0; + return 0; +} + +static void pdp_ieee1394_reset(t_pdp_ieee1394 *x) +{ + OSErr anErr; + + if ( !x->x_initialized ) + { + post("pdp_ieee1394: trying to reset but the sequence grabber is not initialized"); + return; + } + + post("pdp_ieee1394: resetting...."); + + switch (x->x_quality) + { + case 0: + anErr = SGSetChannelPlayFlags(x->x_vc, channelPlayNormal); + post("pdp_ieee1394: set sequence grabber to : normal quality"); + break; + case 1: + anErr = SGSetChannelPlayFlags(x->x_vc, channelPlayHighQuality); + post("pdp_ieee1394: set sequence grabber to : high quality"); + break; + case 2: + anErr = SGSetChannelPlayFlags(x->x_vc, channelPlayFast); + post("pdp_ieee1394: set sequence grabber to : fast quality"); + break; + case 3: + anErr = SGSetChannelPlayFlags(x->x_vc, channelPlayAllData); + post("pdp_ieee1394: set sequence grabber to : play all data"); + break; + } + + post("pdp_ieee1394: done."); +} + +static void pdp_ieee1394_quality(t_pdp_ieee1394 *x, t_floatarg fquality) +{ + if ( ( (t_int)fquality < 0 ) || ( (t_int)fquality > 3 ) ) + { + post("pdp_ieee1394: wrong quality %d", (t_int)fquality ); + return; + } + else + { + x->x_quality = (t_int)fquality; + } +} + +static void pdp_ieee1394_free(t_pdp_ieee1394 *x) +{ + pdp_ieee1394_close(x); +} + +static t_int pdp_ieee1394_init_grabber(t_pdp_ieee1394 *x) +{ + OSErr anErr; + x->x_srcRect.top = 0; + x->x_srcRect.left = 0; + x->x_srcRect.bottom = x->x_height; + x->x_srcRect.right = x->x_width; + + x->x_sg = OpenDefaultComponent(SeqGrabComponentType, 0); + if(x->x_sg==NULL) + { + post("pdp_ieee1394: could not open default component"); + return -1; + } + else + { + post("pdp_ieee1394: opened default component"); + } + + anErr = SGInitialize(x->x_sg); + if(anErr!=noErr) + { + post("pdp_ieee1394: could not initialize sequence grabber"); + return -1; + } + else + { + post("pdp_ieee1394: initialized sequence grabber"); + } + + anErr = SGSetDataRef(x->x_sg, 0, 0, seqGrabDontMakeMovie); + if (anErr != noErr) + { + post("pdp_ieee1394: couldn't set data ref"); + return -1; + } + else + { + post("pdp_ieee1394: set data ref ok."); + } + + anErr = SGNewChannel(x->x_sg, VideoMediaType, &x->x_vc); + if(anErr!=noErr) + { + post("pdp_ieee1394: could not create new sequence grabber channnel"); + return -1; + } + else + { + post("pdp_ieee1394: created new sequence grabber channnel."); + } + + anErr = SGSetChannelBounds(x->x_vc, &x->x_srcRect); + if(anErr!=noErr) + { + post("pdp_ieee1394: could not set sequence grabber ChannelBounds "); + return -1; + } + else + { + post("pdp_ieee1394: set sequence grabber ChannelBounds"); + } + + anErr = SGSetChannelUsage(x->x_vc, seqGrabPreview); + if(anErr!=noErr) + { + post("pdp_ieee1394: could not set sequence grabber ChannelUsage "); + return -1; + } + else + { + post("pdp_ieee1394: set sequence grabber ChannelUsage"); + } + + switch (x->x_quality) + { + case 0: + anErr = SGSetChannelPlayFlags(x->x_vc, channelPlayNormal); + post("pdp_ieee1394: set sequence grabber to : normal quality"); + break; + case 1: + anErr = SGSetChannelPlayFlags(x->x_vc, channelPlayHighQuality); + post("pdp_ieee1394: set sequence grabber to : high quality"); + break; + case 2: + anErr = SGSetChannelPlayFlags(x->x_vc, channelPlayFast); + post("pdp_ieee1394: set sequence grabber to : fast quality"); + break; + case 3: + anErr = SGSetChannelPlayFlags(x->x_vc, channelPlayAllData); + post("pdp_ieee1394: set sequence grabber to : play all data"); + break; + } + + anErr = QTNewGWorldFromPtr (&x->x_srcGWorld, + k422YpCbCr8CodecType, + &x->x_srcRect, + NULL, + NULL, + 0, + x->x_sdata, + x->x_width*2); + if (anErr!= noErr) + { + post ("pdp_ieee1394: QTNewGWorldFromPtr returned %d", anErr); + return -1; + } + + if (NULL == x->x_srcGWorld) + { + post ("pdp_ieee1394: could not allocate off screen"); + return -1; + } + SGSetGWorld(x->x_sg,(CGrafPtr)x->x_srcGWorld, NULL); + SGStartPreview(x->x_sg); + + return 0; +} + +static void pdp_ieee1394_open(t_pdp_ieee1394 *x) +{ + + x->x_initialized = true; + x->x_continue_thread = 1; + + /* create thread */ + if ( x->x_thread_id == 0 ) + { + if ( pdp_ieee1394_init_grabber( x ) != 0 ) + { + post("pdp_ieee1394: grabber initialization failed"); + return; + } + x->x_frame_ready = 0; + pthread_create(&x->x_thread_id, 0, pdp_ieee1394_thread, x); + } +} + +static void pdp_ieee1394_bang(t_pdp_ieee1394 *x) +{ + unsigned char *pQ; + short int *pY, *pU, *pV; + t_int px, py; + + if (!(x->x_continue_thread)) + { + post("pdp_ieee1394: not initialized."); + + if (x->x_auto_open) + { + post("pdp_ieee1394: attempting auto open"); + pdp_ieee1394_open(x); + if (!(x->x_initialized)) + { + post("pdp_ieee1394: auto open failed"); + return; + } + } + else return; + } + + /* do nothing if there is no frame ready */ + if (!x->x_frame_ready) return; + + x->x_packet = pdp_packet_new_image_YCrCb(x->x_width, x->x_height); + x->x_header = pdp_packet_header(x->x_packet); + + if (!x->x_header) + { + post("pdp_ieee1394: FATAL: can't allocate packet"); + return; + } + + x->x_data = (short int *) pdp_packet_data(x->x_packet); + memset( x->x_data, 0x0, (x->x_size+(x->x_size>>1))<<1 ); + pQ = x->x_sdata; + pY = x->x_data; + pV = x->x_data+x->x_size; + pU = x->x_data+x->x_size+(x->x_size>>2); + for ( py=0; py<(t_int)x->x_height; py++ ) + { + for ( px=0; px<(t_int)x->x_width; px++ ) + { + *(pY+py*x->x_width+px) = (*(pQ+1+2*(py*x->x_width+px)))<<7; + if ( px%2 == 0 ) + { + *(pU+((py>>1)*(x->x_width>>1)+(px>>1))) = (*(pQ+2*(py*x->x_width+px))-128)<<8; + } + if ( px%2 == 1 ) + { + *(pV+((py>>1)*(x->x_width>>1)+(px>>1))) = (*(pQ+2*(py*x->x_width+px))-128)<<8; + } + } + } + + pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet); + + x->x_frame_ready = 0; +} + +t_class *pdp_ieee1394_class; + +void *pdp_ieee1394_new(t_floatarg fwidth, t_floatarg fheight) +{ + t_pdp_ieee1394 *x = (t_pdp_ieee1394 *)pd_new(pdp_ieee1394_class); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_initialized = false; + + x->x_auto_open = true; + + x->x_continue_thread = 0; + + if (fwidth > 0.) + { + x->x_width = (int)fwidth; + } + else + { + x->x_width = DEFAULT_WIDTH; + } + + if (fheight > 0.) + { + x->x_height = (int)fheight; + } + else + { + x->x_height = DEFAULT_WIDTH; + } + x->x_size = x->x_width*x->x_height; + x->x_sdata = (unsigned char*) getbytes( (x->x_size+(x->x_size>>1))<<1 ); + if ( !x->x_sdata ) + { + post ("pdp_ieee1394: FATAL : couldn't allocate static data."); + return NULL; + } + + x->x_quality = 1; + x->x_thread_id = 0; + + return (void *)x; +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_ieee1394_setup(void) +{ + pdp_ieee1394_class = class_new(gensym("pdp_ieee1394"), (t_newmethod)pdp_ieee1394_new, + (t_method)pdp_ieee1394_free, sizeof(t_pdp_ieee1394), 0, A_DEFFLOAT, A_DEFFLOAT, A_NULL); + + class_addmethod(pdp_ieee1394_class, (t_method)pdp_ieee1394_bang, 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_NULL); + class_addmethod(pdp_ieee1394_class, (t_method)pdp_ieee1394_reset, gensym("reset"), A_NULL); + class_addmethod(pdp_ieee1394_class, (t_method)pdp_ieee1394_quality, gensym("quality"), A_DEFFLOAT, A_NULL); +} + +#ifdef __cplusplus +} +#endif -- cgit v1.2.1