Home modules.gotpike.org
Username: Password: [Create Account]
[Forgot Password?]

Modules

ADT
Database
GTK2
GUI
IP
PiJAX
Public
Sql
Stdio
Subversion
System
Tools
Xosd
lua
v4l2
wx

Recent Changes

Public.Parser.XML2 1.50
Public.ZeroMQ 1.1
Public.Template.Mustache 1.0
Public.Protocols.XMPP 1.4
Sql.Provider.jdbc 1.0

Popular Downloads

Public.Parser.JSON2 1.0
Public.Parser.JSON 0.2
GTK2 2.23
Public.Web.FCGI 1.8
Public.Parser.XML2 1.48


Module Information
v4l2
Viewing contents of v4l2-0.1/_v4l2.cmod

/* Video 4 Linux v2 module for Pike
   Copyright Ian Carr-de Avelon 2004-2006 
   GPL applies
 */

#define VIDEOMAX 1000000
#include "util.h"
#include "math.h"



//Includes for Pike
#include "global.h"
#include "image.h"

#include "interpret.h"
#include "svalue.h"
#include "module.h"
#include "stralloc.h"
#include "array.h"
#include "pike_macros.h"
#include "program.h"
#include "object.h"
#include "interpret.h"
#include "pike_error.h"
#include "pike_types.h"
#include "threads.h"
#include "dynamic_buffer.h"
#include "builtin_functions.h"

//Includes for v4l2
#include 
#include 
#include 
#include 
#include 
#include           /* for videodev2.h */
#include "videodev2.h"

#include               /* low-level i/o */
#include               /* for errno surprise! */

//#define HAVE_STDINT_H

#define CLEAR(x) memset (&(x), 0, sizeof (x))


struct buffer {
        void *                  start;
        size_t                  length;
};

struct v4l2_state {
	struct buffer * buffers;
	struct v4l2_buffer buf;
	int n_buffers;
};

static int xioctl(int fd, int request, void * arg){
int r;
do r = ioctl (fd, request, arg);
	while (-1 == r && EINTR == errno);
return r;
}


PIKECLASS  lowlevel {
/* Global variables */
CVAR struct v4l2_state  state;



PIKEFUN mapping init(int fd){
int out;
struct v4l2_capability cap;

        out=ioctl (fd, VIDIOC_QUERYCAP, &cap);
	if(out==-1)
		RETURN(0);
//FIXME add checking
pop_n_elems(1);
      push_text("driver");
      push_string(make_shared_string(cap.driver));
      push_text("card");
      push_string(make_shared_string(cap.card));
      push_text("bus_info");
      push_string(make_shared_string(cap.bus_info));
      push_text("version");
      push_int(cap.version);
      push_text("capabilities");
      push_int(cap.capabilities);

  f_aggregate_mapping(10);
}

PIKEFUN mapping enumerate_inputs(int fd, int index){
int out;
struct v4l2_input in;
in.index=index;
pop_n_elems(2);
out=ioctl (fd, VIDIOC_ENUMINPUT, &in);
if(out==-1)
	RETURN(0);
//FIXME add checking
      push_text("index");
      push_int(in.index);
      push_text("name");
      push_string(make_shared_string(in.name));
      push_text("type");
      push_int(in.type);
      push_text("audioset");
      push_int(in.audioset);
      push_text("tuner");
      push_int(in.tuner);
//      push_text("v4l2_std_id");
//      push_int(in.v4l2_std_id);
      push_text("status");
      push_int(in.status);
  f_aggregate_mapping(12);
}

PIKEFUN int current_input(int fd){
int out,*in;

pop_n_elems(1);
        out=ioctl (fd, VIDIOC_G_INPUT, in);
        if(out==-1)
                RETURN(0);
//FIXME add checking
RETURN(*in);
}

PIKEFUN int select_input(int fd){
int out,*in;

pop_n_elems(1);
        out=ioctl (fd, VIDIOC_S_INPUT, in);
        if(out==-1)
                RETURN(0);
//FIXME add checking
RETURN(1);
}

PIKEFUN mapping enumerate_audio(int fd, int index){
int out;
struct v4l2_audio audio;
audio.reserved[0]=0;
audio.reserved[1]=0;
audio.index=index;
out=ioctl (fd, VIDIOC_ENUMAUDIO, &audio);
pop_n_elems(2);
if(out==-1)
        RETURN(0);
//FIXME add checking
      push_text("index");
      push_int(audio.index);
      push_text("name");
      push_string(make_shared_string(audio.name));
      push_text("capability");
      push_int(audio.capability);
      push_text("mode");
      push_int(audio.mode);
  f_aggregate_mapping(8);
}

PIKEFUN mapping current_audio(int fd){
int out;
struct v4l2_audio audio;
audio.reserved[0]=0;
audio.reserved[1]=0;
out=ioctl (fd, VIDIOC_G_AUDIO, &audio);
if(out==-1)
        RETURN(0);
//FIXME add checking
pop_n_elems(1);
      push_text("index");
      push_int(audio.index);
      push_text("name");
      push_string(make_shared_string(audio.name));
      push_text("capability");
      push_int(audio.capability);
      push_text("mode");
      push_int(audio.mode);
  f_aggregate_mapping(8);
}
 

PIKEFUN int set_audio(int fd, int index, int mode){
int out;
struct v4l2_audio audio;
audio.reserved[0]=0;
audio.reserved[1]=0;
audio.index=index;
audio.mode=mode;
pop_n_elems(3);
out=ioctl (fd, VIDIOC_S_AUDIO, &audio);
if(out==-1)
        RETURN(0);
RETURN(1);	
}

PIKEFUN mapping query_tuner(int fd, int index){
int out;
struct v4l2_tuner tuner;
tuner.index=index;
out=ioctl (fd, VIDIOC_G_TUNER, &tuner);
if(out==-1)
        RETURN(0);
pop_n_elems(2);
      push_text("index");
      push_int(tuner.index);
      push_text("name");
      push_string(make_shared_string(tuner.name));
      push_text("type");
      push_int((int)tuner.type);
      push_text("capability");
      push_int(tuner.capability);
      push_text("rangelow");
      push_int(tuner.rangelow);
      push_text("rangehigh");
      push_int(tuner.rangehigh);
      push_text("rxsubchans");
      push_int(tuner.rxsubchans);
  f_aggregate_mapping(14);
}

PIKEFUN int set_tuner_mode(int fd, int index, int mode){
int out;
struct v4l2_audio audio;
audio.index=index;
audio.mode=mode;
out=ioctl (fd, VIDIOC_S_TUNER, &audio);
pop_n_elems(3);
if(out==-1)
        RETURN(0);
RETURN(1);
}
//FIXME and the frequency

PIKEFUN string current_standard(int fd){
int out;
v4l2_std_id standard;

pop_n_elems(1);
out=ioctl (fd, VIDIOC_G_STD, &standard);
if(out==-1)
        RETURN(0);
      push_string(make_shared_binary_string((char*)&standard,8));
}

PIKEFUN string set_standard(int fd, string newstd){
int out;
//IAN check string is 8 characters
out=ioctl (fd, VIDIOC_G_STD, &newstd->str);
pop_n_elems(2);
if(out==-1)
        RETURN(0);
      push_string(make_shared_binary_string((char*)newstd->str,8));
}

PIKEFUN string query_controls(int fd, int id){
int out;
struct v4l2_queryctrl query;
query.id=id;
out=ioctl (fd, VIDIOC_QUERYCTRL, &query);
pop_n_elems(2);
if(out==-1)
        RETURN(0);
      push_text("id");
      push_int(query.id);
      push_text("type");
      push_int((int)query.type);
      push_text("name");
      push_string(make_shared_string(query.name));
      push_text("minimum");
      push_int(query.minimum);
      push_text("maximum");
      push_int(query.maximum);
      push_text("step");
      push_int(query.step);
      push_text("default_value");
      push_int(query.default_value);
      push_text("flags");
      push_int(query.flags);
  f_aggregate_mapping(16);
}

PIKEFUN string query_menu(int fd, int id, int index){
int out;
struct v4l2_querymenu query;
query.id=id;
query.index=index;
out=ioctl (fd, VIDIOC_QUERYMENU, &query);
pop_n_elems(3);
if(out==-1)
        RETURN(0);
      push_text("id");
      push_int(query.id);
      push_text("index");
      push_int(query.index);
      push_text("name");
      push_string(make_shared_string(query.name));
  f_aggregate_mapping(6);
}

PIKEFUN int set_control(int fd, int id, int value){
int out;
struct v4l2_control set;
set.id=id;
set.value=value;
out=ioctl (fd, VIDIOC_S_CTRL, &set);
pop_n_elems(3);
if(out==-1)
        RETURN(0);
RETURN(1);
}

PIKEFUN string enumerate_formats(int fd, int index, int type){
int out;
struct v4l2_fmtdesc query;
query.index=index;
query.type=(enum v4l2_buf_type)type;
out=ioctl (fd, VIDIOC_ENUM_FMT, &query);
pop_n_elems(3);
if(out==-1)
        RETURN(0);
      push_text("index");
      push_int(query.index);
      push_text("type");
      push_int((int)query.type);
      push_text("flags");
      push_int(query.flags);
      push_text("description");
      push_string(make_shared_string(query.description));
      push_text("pixelformat");
      push_int(query.pixelformat);
  f_aggregate_mapping(10);
}

PIKEFUN mapping get_format(int fd){
int out;
struct v4l2_format query;
out=ioctl (fd, VIDIOC_G_FMT, &query);
//if(out==-1)
//        RETURN(0);
pop_n_elems(1);
      push_text("type");
      push_int((int)query.type);
/* FIXME check which type and add information in the union
//v4l2_pix_format
      push_text("width");
      push_int(query.pix.width);
      push_text("height");
      push_int(query.pix.height);
      push_text("pixelformat");
      push_int(query.pix.pixelformat);
      push_text("field");
      push_int((int *)query.pix.field);
      push_text("bytesperline");
      push_int(query.pix.bytesperline);
      push_text("sizeimage");
      push_int(query.pix.sizeimage);
      push_text("colorspace");
      push_int((int *)query.pix.colorspace);
//v4l2_window
//v4l2_rect
      push_text("left");
      push_int(query.win.w.left);
      push_text("top");
      push_int(query.win.w.top);
      push_text("width");
      push_int(query.win.w.width);
      push_text("height");
      push_int(query.win.w.height);
      push_text("field");
      push_int((int *)query.win.field);
      push_text("chromakey");
      push_int(query.win.chromakey);
//FIXME there can be multiple cliping frames
//v4l2_clip
//v4l2_rect
      push_text("clip left");
      push_int(query.win.clips.c.left);
      push_text("clip top");
      push_int(query.win.clips.c.top);
      push_text("clip width");
      push_int(query.win.clips.c.width);
      push_text("clip height");
      push_int(query.win.clips.c.height);
      push_text("clipcount");
      push_int(query.win.clipcount); 
  f_aggregate_mapping(38);
 */
  f_aggregate_mapping(2);
}


PIKEFUN int device_init(int fd, int width, int height){
struct v4l2_capability cap;
struct v4l2_cropcap cropcap;
struct v4l2_crop crop;
struct v4l2_format fmt;
unsigned int min;

pop_n_elems(3);
cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	if (0 == xioctl (fd, VIDIOC_CROPCAP, &cropcap)) {
		crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		crop.c = cropcap.defrect; /* reset to default */
		if (-1 == xioctl (fd, VIDIOC_S_CROP, &crop)) {
			switch (errno) {
				case EINVAL:
                                /* Cropping not supported. */
                                break;
                        default:
                                /* Errors ignored. */
                                break;
                        	}
                	}
        } else {
                /* Errors ignored. */
        }

        CLEAR (fmt);
        fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        fmt.fmt.pix.width       = width;
        fmt.fmt.pix.height      = height;
//saa7134 V4L2_PIX_FMT_RGB24 snafu
        fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
        fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
        if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt)){
		push_int(-1);
		return;
		}
        /* Note VIDIOC_S_FMT may change width and height. */
        /* Buggy driver paranoia. */
        min = fmt.fmt.pix.width * 2;
        if (fmt.fmt.pix.bytesperline < min)
                fmt.fmt.pix.bytesperline = min;
        min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
        if (fmt.fmt.pix.sizeimage < min)
                fmt.fmt.pix.sizeimage = min;
push_int(1);
return;
}

//start grabbing frames using user pointers. 
//"no" is the number of buffers to setup and queue
PIKEFUN int start(int fd, int no){
int i;
enum v4l2_buf_type type;
struct v4l2_requestbuffers reqbuf;
pop_n_elems(2);
memset (&reqbuf, 0, sizeof (reqbuf));
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
reqbuf.count = no;

if (-1 == ioctl (fd, VIDIOC_REQBUFS, &reqbuf)) {
        if (errno == EINVAL){
		push_int(-1);
		return;
		}
	}

THIS->state.buffers = calloc (reqbuf.count, sizeof (*THIS->state.buffers));
//assert (THIS->state.buffers != NULL);
if(THIS->state.buffers == NULL){
	push_int(-10);
	return;
	}

for (i = 0; i < reqbuf.count; i++) {
        struct v4l2_buffer buffer;
        memset (&buffer, 0, sizeof (buffer));
        buffer.type = reqbuf.type;
        buffer.memory = V4L2_MEMORY_MMAP;
        buffer.index = i;
        if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buffer)) {
		push_int(-2);
		return;
		}
        THIS->state.buffers[i].length = buffer.length; /* remember for munmap() */
        THIS->state.buffers[i].start = mmap (NULL, buffer.length,
                                 PROT_READ | PROT_WRITE, /* required */
/*                                 MAP_SHARED,             / * recommended */
/*				MAP_PRIVATE|MAP_ANONYMOUS, / * other Pike uses */
				MAP_SHARED,
                                 fd, buffer.m.offset);
        if (THIS->state.buffers[i].start == MAP_FAILED) {
                /* You may need to unmap and free the so far
                   mapped buffers here. */
		push_int(errno);
//		push_int(-9);
		return;
		}
        }
for (i = 0; i < reqbuf.count; ++i) {
     struct v4l2_buffer buf;
     CLEAR (buf);
     buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     buf.memory      = V4L2_MEMORY_MMAP;
     buf.index       = i;
     if (-1 == xioctl (fd, VIDIOC_QBUF, &buf)){
//		push_int(-2*i);
		push_int(errno);
		return;
		}
	}
THIS->state.n_buffers=reqbuf.count;

type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl (fd, VIDIOC_STREAMON, &type)){
	push_int(-4);
	return;
	}

push_int(reqbuf.count);
return;
}

PIKEFUN int stop(int fd){
enum v4l2_buf_type type;
int i;

pop_n_elems(1);
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1 == xioctl (fd, VIDIOC_STREAMOFF, &type)){
	push_int(0);
	return;
	}
for (i = 0; i < THIS->state.n_buffers; ++i) {
        munmap (THIS->state.buffers[i].start, THIS->state.buffers[i].length);
        }
RETURN(1);
}

PIKEFUN string get_data(int fd){
int i;
struct v4l2_buffer buf;
pop_n_elems(1);
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
      push_string(make_shared_string((char *)strerror(errno)));
	return;
	}

if(buf.index >= THIS->state.n_buffers){
	push_int(-2);
	return;
	}
	
//process_image ((void *) buf.m.userptr);
push_string(make_shared_binary_string((char *)THIS->state.buffers[buf.index].start,THIS->state.buffers[buf.index].length));
if (-1 == xioctl (fd, VIDIOC_QBUF, &buf)){
	push_int(-3);
	return;
	}
return;
}

PIKEFUN object get_image(object rgb, int fd){
struct image *img = NULL;
img=(struct image *)rgb->storage;
rgb_group *pixels;
pixels=img->img;
int i;
char save;
COLORTYPE *data; 
struct v4l2_buffer buf;

pop_n_elems(2);
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
      push_string(make_shared_string((char *)strerror(errno)));
	return;
	}

if(buf.index >= THIS->state.n_buffers){
	push_int(-2);
	return;
	}
	
//memcpy(img->img,(rgb_group *)THIS->state.buffers[buf.index].start,(size_t)THIS->state.buffers[buf.index].length);
//The kernel module gives us RGB, and could give us BGR, but Pike seems to
//use GRB
data=(__u8*)THIS->state.buffers[buf.index].start;
// 3green shown blue, 2red shown green, 
for(i=0;ixsize*img->ysize;i++){
	pixels->b=*data++;
	pixels->r=*data++;
	pixels->g=*data++;
	pixels++;
	data++;
	}
if (-1 == xioctl (fd, VIDIOC_QBUF, &buf)){
	push_int(-3);
	return;
	}
ref_push_object(rgb);
return;
}


}//end class


gotpike.org | Copyright © 2004 - 2019 | Pike is a trademark of Department of Computer and Information Science, Linköping University