| /********************************************************** |
| Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, |
| The Netherlands. |
| |
| All Rights Reserved |
| |
| Permission to use, copy, modify, and distribute this software and its |
| documentation for any purpose and without fee is hereby granted, |
| provided that the above copyright notice appear in all copies and that |
| both that copyright notice and this permission notice appear in |
| supporting documentation, and that the names of Stichting Mathematisch |
| Centrum or CWI not be used in advertising or publicity pertaining to |
| distribution of the software without specific, written prior permission. |
| |
| STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO |
| THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE |
| FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
| OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| |
| ******************************************************************/ |
| |
| /* SV module -- interface to the Indigo video board */ |
| |
| #include <sys/time.h> |
| #include <svideo.h> |
| #include "allobjects.h" |
| #include "import.h" |
| #include "modsupport.h" |
| #include "compile.h" |
| #include "ceval.h" |
| #include "yuv.h" /* for YUV conversion functions */ |
| |
| typedef struct { |
| OB_HEAD |
| SV_nodeP ob_svideo; |
| svCaptureInfo ob_info; |
| } svobject; |
| |
| typedef struct { |
| OB_HEAD |
| void *ob_capture; |
| int ob_mustunlock; |
| svCaptureInfo ob_info; |
| svobject *ob_svideo; |
| } captureobject; |
| |
| static object *SvError; /* exception sv.error */ |
| |
| static object *newcaptureobject PROTO((svobject *, void *, int)); |
| |
| /* Set a SV-specific error from svideo_errno and return NULL */ |
| static object * |
| sv_error() |
| { |
| err_setstr(SvError, svStrerror(svideo_errno)); |
| return NULL; |
| } |
| |
| static object * |
| svc_conversion(self, args, function, factor) |
| captureobject *self; |
| object *args; |
| void (*function)(); |
| float factor; |
| { |
| object *output; |
| int invert; |
| |
| if (!getargs(args, "i", &invert)) |
| return NULL; |
| |
| output = newsizedstringobject(NULL, (int) (self->ob_info.width * self->ob_info.height * factor)); |
| if (output == NULL) |
| return NULL; |
| |
| (*function)((boolean) invert, self->ob_capture, getstringvalue(output), |
| self->ob_info.width, self->ob_info.height); |
| |
| return output; |
| } |
| |
| /* |
| * 3 functions to convert from Starter Video YUV 4:1:1 format to |
| * Compression Library 4:2:2 Duplicate Chroma format. |
| */ |
| static object * |
| svc_YUVtoYUV422DC(self, args) |
| captureobject *self; |
| object *args; |
| { |
| if (self->ob_info.format != SV_YUV411_FRAMES) { |
| err_setstr(SvError, "data has bad format"); |
| return NULL; |
| } |
| return svc_conversion(self, args, yuv_sv411_to_cl422dc, 2.0); |
| } |
| |
| static object * |
| svc_YUVtoYUV422DC_quarter(self, args) |
| captureobject *self; |
| object *args; |
| { |
| if (self->ob_info.format != SV_YUV411_FRAMES) { |
| err_setstr(SvError, "data has bad format"); |
| return NULL; |
| } |
| return svc_conversion(self, args, yuv_sv411_to_cl422dc_quartersize, 0.5); |
| } |
| |
| static object * |
| svc_YUVtoYUV422DC_sixteenth(self, args) |
| captureobject *self; |
| object *args; |
| { |
| if (self->ob_info.format != SV_YUV411_FRAMES) { |
| err_setstr(SvError, "data has bad format"); |
| return NULL; |
| } |
| return svc_conversion(self, args, yuv_sv411_to_cl422dc_sixteenthsize, 0.125); |
| } |
| |
| static object * |
| svc_YUVtoRGB(self, args) |
| captureobject *self; |
| object *args; |
| { |
| switch (self->ob_info.format) { |
| case SV_YUV411_FRAMES: |
| case SV_YUV411_FRAMES_AND_BLANKING_BUFFER: |
| break; |
| default: |
| err_setstr(SvError, "data had bad format"); |
| return NULL; |
| } |
| return svc_conversion(self, args, svYUVtoRGB, (float) sizeof(long)); |
| } |
| |
| static object * |
| svc_RGB8toRGB32(self, args) |
| captureobject *self; |
| object *args; |
| { |
| if (self->ob_info.format != SV_RGB8_FRAMES) { |
| err_setstr(SvError, "data has bad format"); |
| return NULL; |
| } |
| return svc_conversion(self, args, svRGB8toRGB32, (float) sizeof(long)); |
| } |
| |
| static object * |
| svc_InterleaveFields(self, args) |
| captureobject *self; |
| object *args; |
| { |
| if (self->ob_info.format != SV_RGB8_FRAMES) { |
| err_setstr(SvError, "data has bad format"); |
| return NULL; |
| } |
| return svc_conversion(self, args, svInterleaveFields, 1.0); |
| } |
| |
| static object * |
| svc_GetFields(self, args) |
| captureobject *self; |
| object *args; |
| { |
| object *f1, *f2, *ret; |
| int fieldsize; |
| |
| if (self->ob_info.format != SV_RGB8_FRAMES) { |
| err_setstr(SvError, "data has bad format"); |
| return NULL; |
| } |
| |
| fieldsize = self->ob_info.width * self->ob_info.height / 2; |
| f1 = newsizedstringobject((char *) self->ob_capture, fieldsize); |
| f2 = newsizedstringobject((char *) self->ob_capture + fieldsize, fieldsize); |
| ret = mkvalue("(OO)", f1, f2); |
| XDECREF(f1); |
| XDECREF(f2); |
| return ret; |
| } |
| |
| static object * |
| svc_UnlockCaptureData(self, args) |
| captureobject *self; |
| object *args; |
| { |
| if (!getnoarg(args)) |
| return NULL; |
| |
| if (!self->ob_mustunlock) { |
| err_setstr(SvError, "buffer should not be unlocked"); |
| return NULL; |
| } |
| |
| if (svUnlockCaptureData(self->ob_svideo->ob_svideo, self->ob_capture)) |
| return sv_error(); |
| |
| self->ob_mustunlock = 0; |
| |
| INCREF(None); |
| return None; |
| } |
| |
| #ifdef USE_GL |
| #include <gl.h> |
| |
| static object * |
| svc_lrectwrite(self, args) |
| captureobject *self; |
| object *args; |
| { |
| Screencoord x1, x2, y1, y2; |
| |
| if (!getargs(args, "(hhhh)", &x1, &x2, &y1, &y2)) |
| return NULL; |
| |
| lrectwrite(x1, x2, y1, y2, (unsigned long *) self->ob_capture); |
| |
| INCREF(None); |
| return None; |
| } |
| #endif |
| |
| static object * |
| svc_writefile(self, args) |
| captureobject *self; |
| object *args; |
| { |
| object *file; |
| int size; |
| |
| if (!getargs(args, "O", &file)) |
| return NULL; |
| |
| if (!is_fileobject(file)) { |
| err_setstr(SvError, "not a file object"); |
| return NULL; |
| } |
| |
| size = self->ob_info.width * self->ob_info.height; |
| |
| if (fwrite(self->ob_capture, sizeof(long), size, getfilefile(file)) != size) { |
| err_setstr(SvError, "writing failed"); |
| return NULL; |
| } |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| svc_FindVisibleRegion(self, args) |
| captureobject *self; |
| object *args; |
| { |
| void *visible; |
| int width; |
| |
| if (!getnoarg(args)) |
| return NULL; |
| |
| if (svFindVisibleRegion(self->ob_svideo->ob_svideo, self->ob_capture, &visible, self->ob_info.width)) |
| return sv_error(); |
| |
| if (visible == NULL) { |
| err_setstr(SvError, "data in wrong format"); |
| return NULL; |
| } |
| |
| return newcaptureobject(self->ob_svideo, visible, 0); |
| } |
| |
| static struct methodlist capture_methods[] = { |
| {"YUVtoRGB", (method)svc_YUVtoRGB}, |
| {"RGB8toRGB32", (method)svc_RGB8toRGB32}, |
| {"InterleaveFields", (method)svc_InterleaveFields}, |
| {"UnlockCaptureData", (method)svc_UnlockCaptureData}, |
| {"FindVisibleRegion", (method)svc_FindVisibleRegion}, |
| {"GetFields", (method)svc_GetFields}, |
| {"YUVtoYUV422DC", (method)svc_YUVtoYUV422DC}, |
| {"YUVtoYUV422DC_quarter",(method)svc_YUVtoYUV422DC_quarter}, |
| {"YUVtoYUV422DC_sixteenth",(method)svc_YUVtoYUV422DC_sixteenth}, |
| #ifdef USE_GL |
| {"lrectwrite", (method)svc_lrectwrite}, |
| #endif |
| {"writefile", (method)svc_writefile}, |
| {NULL, NULL} /* sentinel */ |
| }; |
| |
| static void |
| capture_dealloc(self) |
| captureobject *self; |
| { |
| if (self->ob_capture != NULL) { |
| if (self->ob_mustunlock) |
| (void) svUnlockCaptureData(self->ob_svideo->ob_svideo, self->ob_capture); |
| self->ob_capture = NULL; |
| DECREF(self->ob_svideo); |
| self->ob_svideo = NULL; |
| } |
| DEL(self); |
| } |
| |
| static object * |
| capture_getattr(self, name) |
| svobject *self; |
| char *name; |
| { |
| return findmethod(capture_methods, (object *)self, name); |
| } |
| |
| typeobject Capturetype = { |
| OB_HEAD_INIT(&Typetype) |
| 0, /*ob_size*/ |
| "capture", /*tp_name*/ |
| sizeof(captureobject), /*tp_size*/ |
| 0, /*tp_itemsize*/ |
| /* methods */ |
| (destructor)capture_dealloc, /*tp_dealloc*/ |
| 0, /*tp_print*/ |
| (getattrfunc)capture_getattr, /*tp_getattr*/ |
| 0, /*tp_setattr*/ |
| 0, /*tp_compare*/ |
| 0, /*tp_repr*/ |
| }; |
| |
| static object * |
| newcaptureobject(self, ptr, mustunlock) |
| svobject *self; |
| void *ptr; |
| int mustunlock; |
| { |
| captureobject *p; |
| |
| p = NEWOBJ(captureobject, &Capturetype); |
| if (p == NULL) |
| return NULL; |
| p->ob_svideo = self; |
| INCREF(self); |
| p->ob_capture = ptr; |
| p->ob_mustunlock = mustunlock; |
| p->ob_info = self->ob_info; |
| return (object *) p; |
| } |
| |
| static object * |
| sv_GetCaptureData(self, args) |
| svobject *self; |
| object *args; |
| { |
| void *ptr; |
| long fieldID; |
| object *res, *c; |
| |
| if (!getnoarg(args)) |
| return NULL; |
| |
| if (svGetCaptureData(self->ob_svideo, &ptr, &fieldID)) |
| return sv_error(); |
| |
| if (ptr == NULL) { |
| err_setstr(SvError, "no data available"); |
| return NULL; |
| } |
| |
| c = newcaptureobject(self, ptr, 1); |
| if (c == NULL) |
| return NULL; |
| res = mkvalue("(Oi)", c, fieldID); |
| DECREF(c); |
| return res; |
| } |
| |
| static object * |
| sv_BindGLWindow(self, args) |
| svobject *self; |
| object *args; |
| { |
| long wid; |
| int mode; |
| |
| if (!getargs(args, "(ii)", &wid, &mode)) |
| return NULL; |
| |
| if (svBindGLWindow(self->ob_svideo, wid, mode)) |
| return sv_error(); |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| sv_EndContinuousCapture(self, args) |
| svobject *self; |
| object *args; |
| { |
| |
| if (!getnoarg(args)) |
| return NULL; |
| |
| if (svEndContinuousCapture(self->ob_svideo)) |
| return sv_error(); |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| sv_IsVideoDisplayed(self, args) |
| svobject *self; |
| object *args; |
| { |
| int v; |
| |
| if (!getnoarg(args)) |
| return NULL; |
| |
| v = svIsVideoDisplayed(self->ob_svideo); |
| if (v == -1) |
| return sv_error(); |
| |
| return newintobject((long) v); |
| } |
| |
| static object * |
| sv_OutputOffset(self, args) |
| svobject *self; |
| object *args; |
| { |
| int x_offset; |
| int y_offset; |
| |
| if (!getargs(args, "(ii)", &x_offset, &y_offset)) |
| return NULL; |
| |
| if (svOutputOffset(self->ob_svideo, x_offset, y_offset)) |
| return sv_error(); |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| sv_PutFrame(self, args) |
| svobject *self; |
| object *args; |
| { |
| char *buffer; |
| |
| if (!getargs(args, "s", &buffer)) |
| return NULL; |
| |
| if (svPutFrame(self->ob_svideo, buffer)) |
| return sv_error(); |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| sv_QuerySize(self, args) |
| svobject *self; |
| object *args; |
| { |
| int w; |
| int h; |
| int rw; |
| int rh; |
| |
| if (!getargs(args, "(ii)", &w, &h)) |
| return NULL; |
| |
| if (svQuerySize(self->ob_svideo, w, h, &rw, &rh)) |
| return sv_error(); |
| |
| return mkvalue("(ii)", (long) rw, (long) rh); |
| } |
| |
| static object * |
| sv_SetSize(self, args) |
| svobject *self; |
| object *args; |
| { |
| int w; |
| int h; |
| |
| if (!getargs(args, "(ii)", &w, &h)) |
| return NULL; |
| |
| if (svSetSize(self->ob_svideo, w, h)) |
| return sv_error(); |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| sv_SetStdDefaults(self, args) |
| svobject *self; |
| object *args; |
| { |
| |
| if (!getnoarg(args)) |
| return NULL; |
| |
| if (svSetStdDefaults(self->ob_svideo)) |
| return sv_error(); |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| sv_UseExclusive(self, args) |
| svobject *self; |
| object *args; |
| { |
| boolean onoff; |
| int mode; |
| |
| if (!getargs(args, "(ii)", &onoff, &mode)) |
| return NULL; |
| |
| if (svUseExclusive(self->ob_svideo, onoff, mode)) |
| return sv_error(); |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| sv_WindowOffset(self, args) |
| svobject *self; |
| object *args; |
| { |
| int x_offset; |
| int y_offset; |
| |
| if (!getargs(args, "(ii)", &x_offset, &y_offset)) |
| return NULL; |
| |
| if (svWindowOffset(self->ob_svideo, x_offset, y_offset)) |
| return sv_error(); |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| sv_CaptureBurst(self, args) |
| svobject *self; |
| object *args; |
| { |
| int bytes, i; |
| svCaptureInfo info; |
| void *bitvector = NULL; |
| object *videodata, *bitvecobj, *res; |
| static object *evenitem, *odditem; |
| |
| if (!getargs(args, "(iiiii)", &info.format, &info.width, &info.height, |
| &info.size, &info.samplingrate)) |
| return NULL; |
| |
| switch (info.format) { |
| case SV_RGB8_FRAMES: |
| bitvector = malloc(SV_BITVEC_SIZE(info.size)); |
| break; |
| case SV_YUV411_FRAMES_AND_BLANKING_BUFFER: |
| break; |
| default: |
| err_setstr(SvError, "illegal format specified"); |
| return NULL; |
| } |
| |
| if (svQueryCaptureBufferSize(self->ob_svideo, &info, &bytes)) { |
| if (bitvector) |
| free(bitvector); |
| return sv_error(); |
| } |
| |
| videodata = newsizedstringobject(NULL, bytes); |
| if (videodata == NULL) { |
| if (bitvector) |
| free(bitvector); |
| return NULL; |
| } |
| |
| /* XXX -- need to do something about the bitvector */ |
| if (svCaptureBurst(self->ob_svideo, &info, getstringvalue(videodata), |
| bitvector)) { |
| if (bitvector) |
| free(bitvector); |
| DECREF(videodata); |
| return sv_error(); |
| } |
| |
| if (bitvector) { |
| if (evenitem == NULL) { |
| evenitem = newintobject(0); |
| if (evenitem == NULL) { |
| free(bitvector); |
| DECREF(videodata); |
| return NULL; |
| } |
| } |
| if (odditem == NULL) { |
| odditem = newintobject(1); |
| if (odditem == NULL) { |
| free(bitvector); |
| DECREF(videodata); |
| return NULL; |
| } |
| } |
| bitvecobj = newtupleobject(2 * info.size); |
| if (bitvecobj == NULL) { |
| free(bitvecobj); |
| DECREF(videodata); |
| return NULL; |
| } |
| for (i = 0; i < 2 * info.size; i++) { |
| if (SV_GET_FIELD(bitvector, i) == SV_EVEN_FIELD) { |
| INCREF(evenitem); |
| settupleitem(bitvecobj, i, evenitem); |
| } else { |
| INCREF(odditem); |
| settupleitem(bitvecobj, i, odditem); |
| } |
| } |
| free(bitvector); |
| } else { |
| bitvecobj = None; |
| INCREF(None); |
| } |
| |
| res = mkvalue("((iiiii)OO)", info.format, info.width, info.height, |
| info.size, info.samplingrate, videodata, bitvecobj); |
| DECREF(videodata); |
| DECREF(bitvecobj); |
| return res; |
| } |
| |
| static object * |
| sv_CaptureOneFrame(self, args) |
| svobject *self; |
| object *args; |
| { |
| svCaptureInfo info; |
| int format, width, height; |
| int bytes; |
| object *videodata, *res; |
| |
| if (!getargs(args, "(iii)", &format, &width, &height)) |
| return NULL; |
| info.format = format; |
| info.width = width; |
| info.height = height; |
| info.size = 0; |
| info.samplingrate = 0; |
| if (svQueryCaptureBufferSize(self->ob_svideo, &info, &bytes)) |
| return sv_error(); |
| videodata = newsizedstringobject(NULL, bytes); |
| if (videodata == NULL) |
| return NULL; |
| if (svCaptureOneFrame(self->ob_svideo, format, &width, &height, |
| getstringvalue(videodata))) { |
| DECREF(videodata); |
| return sv_error(); |
| } |
| |
| res = mkvalue("(iiO)", width, height, videodata); |
| DECREF(videodata); |
| return res; |
| } |
| |
| static object * |
| sv_InitContinuousCapture(self, args) |
| svobject *self; |
| object *args; |
| { |
| svCaptureInfo info; |
| |
| if (!getargs(args, "(iiiii)", &info.format, &info.width, &info.height, |
| &info.size, &info.samplingrate)) |
| return NULL; |
| |
| if (svInitContinuousCapture(self->ob_svideo, &info)) |
| return sv_error(); |
| |
| self->ob_info = info; |
| |
| return mkvalue("(iiiii)", info.format, info.width, info.height, |
| info.size, info.samplingrate); |
| } |
| |
| static object * |
| sv_LoadMap(self, args) |
| svobject *self; |
| object *args; |
| { |
| object *rgb, *v, *cell; |
| rgb_tuple *mapp; |
| int maptype; |
| int i, j; /* indices */ |
| |
| if (!getargs(args, "(iO)", &maptype, &rgb)) |
| return NULL; |
| if (!is_listobject(rgb) || getlistsize(rgb) != 256) { |
| err_badarg(); |
| return NULL; |
| } |
| mapp = NEW(rgb_tuple, 256); |
| if (mapp == NULL) |
| return err_nomem(); |
| for (i = 0; i < 256; i++) { |
| v = getlistitem(rgb, i); |
| if (!is_tupleobject(v) || gettuplesize(v) != 3) { |
| DEL(mapp); |
| err_badarg(); |
| return NULL; |
| } |
| for (j = 0; j < 3; j++) { |
| cell = gettupleitem(v, j); |
| if (!is_intobject(cell)) { |
| DEL(mapp); |
| err_badarg(); |
| return NULL; |
| } |
| switch (j) { |
| case 0: mapp[i].red = getintvalue(cell); break; |
| case 1: mapp[i].blue = getintvalue(cell); break; |
| case 2: mapp[i].green = getintvalue(cell); break; |
| } |
| } |
| } |
| |
| if (svLoadMap(self->ob_svideo, maptype, mapp)) { |
| DEL(mapp); |
| return sv_error(); |
| } |
| |
| DEL(mapp); |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| sv_CloseVideo(self, args) |
| svobject *self; |
| object *args; |
| { |
| if (!getnoarg(args)) |
| return NULL; |
| |
| if (svCloseVideo(self->ob_svideo)) |
| return sv_error(); |
| self->ob_svideo = NULL; |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| doParams(self, args, func, modified) |
| svobject *self; |
| object *args; |
| int (*func)(SV_nodeP, long *, int); |
| int modified; |
| { |
| object *list, *v; |
| long *PVbuffer; |
| long length; |
| int i; |
| |
| if (!getargs(args, "O", &list)) |
| return NULL; |
| if (!is_listobject(list)) { |
| err_badarg(); |
| return NULL; |
| } |
| length = getlistsize(list); |
| PVbuffer = NEW(long, length); |
| if (PVbuffer == NULL) |
| return err_nomem(); |
| for (i = 0; i < length; i++) { |
| v = getlistitem(list, i); |
| if (!is_intobject(v)) { |
| DEL(PVbuffer); |
| err_badarg(); |
| return NULL; |
| } |
| PVbuffer[i] = getintvalue(v); |
| } |
| |
| if ((*func)(self->ob_svideo, PVbuffer, length)) { |
| DEL(PVbuffer); |
| return sv_error(); |
| } |
| |
| if (modified) { |
| for (i = 0; i < length; i++) |
| setlistitem(list, i, newintobject(PVbuffer[i])); |
| } |
| |
| DEL(PVbuffer); |
| |
| INCREF(None); |
| return None; |
| } |
| |
| static object * |
| sv_GetParam(self, args) |
| object *self, *args; |
| { |
| return doParams(self, args, svGetParam, 1); |
| } |
| |
| static object * |
| sv_GetParamRange(self, args) |
| object *self, *args; |
| { |
| return doParams(self, args, svGetParamRange, 1); |
| } |
| |
| static object * |
| sv_SetParam(self, args) |
| object *self, *args; |
| { |
| return doParams(self, args, svSetParam, 0); |
| } |
| |
| static struct methodlist svideo_methods[] = { |
| {"BindGLWindow", (method)sv_BindGLWindow}, |
| {"EndContinuousCapture",(method)sv_EndContinuousCapture}, |
| {"IsVideoDisplayed", (method)sv_IsVideoDisplayed}, |
| {"OutputOffset", (method)sv_OutputOffset}, |
| {"PutFrame", (method)sv_PutFrame}, |
| {"QuerySize", (method)sv_QuerySize}, |
| {"SetSize", (method)sv_SetSize}, |
| {"SetStdDefaults", (method)sv_SetStdDefaults}, |
| {"UseExclusive", (method)sv_UseExclusive}, |
| {"WindowOffset", (method)sv_WindowOffset}, |
| {"InitContinuousCapture",(method)sv_InitContinuousCapture}, |
| {"CaptureBurst", (method)sv_CaptureBurst}, |
| {"CaptureOneFrame", (method)sv_CaptureOneFrame}, |
| {"GetCaptureData", (method)sv_GetCaptureData}, |
| {"CloseVideo", (method)sv_CloseVideo}, |
| {"LoadMap", (method)sv_LoadMap}, |
| {"GetParam", (method)sv_GetParam}, |
| {"GetParamRange", (method)sv_GetParamRange}, |
| {"SetParam", (method)sv_SetParam}, |
| {NULL, NULL} /* sentinel */ |
| }; |
| |
| static object * |
| sv_conversion(self, args, function, inputfactor, factor) |
| object *self, *args; |
| void (*function)(); |
| int inputfactor; |
| float factor; |
| { |
| int invert, width, height, inputlength; |
| char *input; |
| object *output; |
| |
| if (!getargs(args, "(is#ii)", &invert, &input, &inputlength, &width, &height)) |
| return NULL; |
| |
| if (width * height * inputfactor > inputlength) { |
| err_setstr(SvError, "input buffer not long enough"); |
| return NULL; |
| } |
| |
| output = newsizedstringobject(NULL, (int) (width * height * factor)); |
| if (output == NULL) |
| return NULL; |
| |
| (*function)(invert, input, getstringvalue(output), width, height); |
| |
| return output; |
| } |
| |
| static object * |
| sv_InterleaveFields(self, args) |
| object *self, *args; |
| { |
| return sv_conversion(self, args, svInterleaveFields, 1, 1.0); |
| } |
| |
| static object * |
| sv_RGB8toRGB32(self, args) |
| object *self, *args; |
| { |
| return sv_conversion(self, args, svRGB8toRGB32, 1, (float) sizeof(long)); |
| } |
| |
| static object * |
| sv_YUVtoRGB(self, args) |
| object *self, *args; |
| { |
| return sv_conversion(self, args, svYUVtoRGB, 2, (float) sizeof(long)); |
| } |
| |
| static void |
| svideo_dealloc(self) |
| svobject *self; |
| { |
| if (self->ob_svideo != NULL) |
| (void) svCloseVideo(self->ob_svideo); |
| DEL(self); |
| } |
| |
| static object * |
| svideo_getattr(self, name) |
| svobject *self; |
| char *name; |
| { |
| return findmethod(svideo_methods, (object *)self, name); |
| } |
| |
| typeobject Svtype = { |
| OB_HEAD_INIT(&Typetype) |
| 0, /*ob_size*/ |
| "sv", /*tp_name*/ |
| sizeof(svobject), /*tp_size*/ |
| 0, /*tp_itemsize*/ |
| /* methods */ |
| (destructor)svideo_dealloc, /*tp_dealloc*/ |
| 0, /*tp_print*/ |
| (getattrfunc)svideo_getattr, /*tp_getattr*/ |
| 0, /*tp_setattr*/ |
| 0, /*tp_compare*/ |
| 0, /*tp_repr*/ |
| }; |
| |
| static object * |
| newsvobject(svp) |
| SV_nodeP svp; |
| { |
| svobject *p; |
| |
| p = NEWOBJ(svobject, &Svtype); |
| if (p == NULL) |
| return NULL; |
| p->ob_svideo = svp; |
| p->ob_info.format = 0; |
| p->ob_info.size = 0; |
| p->ob_info.width = 0; |
| p->ob_info.height = 0; |
| p->ob_info.samplingrate = 0; |
| return (object *) p; |
| } |
| |
| static object * |
| sv_OpenVideo(self, args) |
| object *self, *args; |
| { |
| SV_nodeP svp; |
| |
| if (!getnoarg(args)) |
| return NULL; |
| |
| svp = svOpenVideo(); |
| if (svp == NULL) |
| return sv_error(); |
| |
| return newsvobject(svp); |
| } |
| |
| static struct methodlist sv_methods[] = { |
| {"InterleaveFields", (method)sv_InterleaveFields}, |
| {"RGB8toRGB32", (method)sv_RGB8toRGB32}, |
| {"YUVtoRGB", (method)sv_YUVtoRGB}, |
| {"OpenVideo", (method)sv_OpenVideo}, |
| {NULL, NULL} /* Sentinel */ |
| }; |
| |
| void |
| initsv() |
| { |
| object *m, *d; |
| |
| m = initmodule("sv", sv_methods); |
| d = getmoduledict(m); |
| |
| SvError = newstringobject("sv.error"); |
| if (SvError == NULL || dictinsert(d, "error", SvError) != 0) |
| fatal("can't define sv.error"); |
| } |