lms-video/Gem/plugins/recordV4L2/recordV4L2.cpp
Santi Noreña e85d191b46 - Reestructuración de ficheros y directorios general
- merge v0.01 --> Añadido fileselector
- Añadidas fuentes de Gem y Pure Data
- pix2jpg incluído en Gem. Archivos de construcción de Gem modificados.
- Añadido fichero ompiling.txt con instrucciones de compilación
2013-02-04 18:00:17 +01:00

225 lines
5.5 KiB
C++

////////////////////////////////////////////////////////
//
// GEM - Graphics Environment for Multimedia
//
// zmoelnig@iem.kug.ac.at
//
// Implementation file
//
// Copyright (c) 1997-1999 Mark Danks.
// Copyright (c) Günther Geiger.
// Copyright (c) 2001-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
//
/////////////////////////////////////////////////////////
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "recordV4L2.h"
#include "Gem/Manager.h"
#include "Gem/Exception.h"
#include "plugins/PluginFactory.h"
using namespace gem::plugins;
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
REGISTER_RECORDFACTORY("V4L2", recordV4L2);
/////////////////////////////////////////////////////////
//
// recordV4L2
//
/////////////////////////////////////////////////////////
// Constructor
//
/////////////////////////////////////////////////////////
recordV4L2 :: recordV4L2(void):
m_fd(-1)
{
m_image.xsize=720;
m_image.xsize=576;
m_image.setCsizeByFormat(GL_YUV422_GEM);
//m_image.setCsizeByFormat(GL_RGBA); /* RGBA works with Gem, but not with GStreamer and xawtv */
m_image.reallocate();
switch(m_image.format) {
case GL_YUV422_GEM: m_palette = V4L2_PIX_FMT_UYVY; break;
case GL_LUMINANCE: m_palette = V4L2_PIX_FMT_GREY; break;
case GL_RGBA: m_palette = V4L2_PIX_FMT_RGB32; break;
default: throw(GemException("invalid colorspace"));
}
}
////////////////////////////////////////////////////////
// Destructor
//
/////////////////////////////////////////////////////////
recordV4L2 :: ~recordV4L2(void)
{
stop();
}
void recordV4L2 :: stop(void)
{
if(m_fd>=0)
::close(m_fd);
m_fd=-1;
}
bool recordV4L2 :: start(const std::string filename, gem::Properties&props)
{
stop();
m_fd=::open(filename.c_str(), O_RDWR);
if(m_fd<0)
return false;
struct v4l2_capability vid_caps;
if(ioctl(m_fd, VIDIOC_QUERYCAP, &vid_caps) == -1) {
perror("VIDIOC_QUERYCAP");
stop();
return false;
}
if( !(vid_caps.capabilities & V4L2_CAP_VIDEO_OUTPUT) ) {
verbose(1, "device '%s' is not a video4linux2 output device");
stop();
return false;
}
m_init=false;
return true;
}
bool recordV4L2::init(const imageStruct* dummyImage, const int framedur) {
if(m_init)return true;
if(m_fd<0)return false;
unsigned int w=dummyImage->xsize;
unsigned int h=dummyImage->ysize;
struct v4l2_capability vid_caps;
if(ioctl(m_fd, VIDIOC_QUERYCAP, &vid_caps) == -1) {
perror("VIDIOC_QUERYCAP");
stop(); return false;
}
struct v4l2_format vid_format;
memset(&vid_format, 0, sizeof(vid_format));
vid_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
vid_format.fmt.pix.width = w;
vid_format.fmt.pix.height = h;
vid_format.fmt.pix.pixelformat = m_palette;
vid_format.fmt.pix.sizeimage = w * h * m_image.csize;
vid_format.fmt.pix.field = V4L2_FIELD_NONE;
vid_format.fmt.pix.bytesperline = w * m_image.csize;
//vid_format.fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
vid_format.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
int format= vid_format.fmt.pix.pixelformat;
verbose(1, "v4l2-output requested %dx%d @ '%c%c%c%c'", vid_format.fmt.pix.width, vid_format.fmt.pix.height,
(char)(format),
(char)(format>>8),
(char)(format>>16),
(char)(format>>24));
if(ioctl(m_fd, VIDIOC_S_FMT, &vid_format) == -1) {
perror("VIDIOC_S_FMT");
stop(); return false;
}
verbose(1, "v4l2-output returned %dx%d @ '%c%c%c%c'", vid_format.fmt.pix.width, vid_format.fmt.pix.height,
(char)(format),
(char)(format>>8),
(char)(format>>16),
(char)(format>>24));
/* if the driver returns a format other than requested we should adjust! */
w=vid_format.fmt.pix.width;
h=vid_format.fmt.pix.height;
m_image.xsize=w;
m_image.ysize=h;
m_image.reallocate();
::write(m_fd, m_image.data, m_image.xsize*m_image.ysize*m_image.csize);
m_init=true;
return true;
}
/////////////////////////////////////////////////////////
// do the actual encoding and writing to file
//
/////////////////////////////////////////////////////////
bool recordV4L2 :: write(imageStruct*img)
{
if(!m_init){
if(!init(img, 0))
return true;
}
m_image.convertFrom(img);
// m_image.upsidedown=!m_image.upsidedown;
m_image.fixUpDown();
int size=m_image.xsize*m_image.ysize*m_image.csize;
::write(m_fd, m_image.data, size);
return true;
}
static const std::string s_codec_name=std::string("v4l2");
static const std::string s_codec_desc=std::string("v4l2 loopback device");
/////////////////////////////////////////////////////////
// set codec by name
//
/////////////////////////////////////////////////////////
bool recordV4L2 :: setCodec(const std::string name)
{
if(name==s_codec_name)
return true;
return false;
}
/////////////////////////////////////////////////////////
// get codecs
//
/////////////////////////////////////////////////////////
std::vector<std::string>recordV4L2::getCodecs(void) {
std::vector<std::string>result;
result.push_back(s_codec_name);
return result;
}
const std::string recordV4L2::getCodecDescription(const std::string codec) {
std::string result;
if(codec==s_codec_name)
result=s_codec_desc;
return result;
}
bool recordV4L2::enumProperties(gem::Properties&props) {
props.clear();
return false;
}