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
|
|
|