- 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
This commit is contained in:
parent
c9adfd020b
commit
e85d191b46
3100 changed files with 775434 additions and 3073 deletions
497
Gem/plugins/videoDV4L/videoDV4L.cpp
Normal file
497
Gem/plugins/videoDV4L/videoDV4L.cpp
Normal file
|
@ -0,0 +1,497 @@
|
|||
////////////////////////////////////////////////////////
|
||||
//
|
||||
// GEM - Graphics Environment for Multimedia
|
||||
//
|
||||
// zmoelnig@iem.kug.ac.at
|
||||
//
|
||||
// Implementation file
|
||||
//
|
||||
// Copyright (c) 1997-1998 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 "videoDV4L.h"
|
||||
#include "plugins/PluginFactory.h"
|
||||
using namespace gem::plugins;
|
||||
|
||||
#include "Gem/RTE.h"
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_DV
|
||||
#define MAX_PORTNUM 64
|
||||
|
||||
#if 0
|
||||
# define DEBUG_WHERE post("%s:%d\t%s", __FILE__, __LINE__, __FUNCTION__)
|
||||
#else
|
||||
# define DEBUG_WHERE
|
||||
#endif
|
||||
|
||||
|
||||
REGISTER_VIDEOFACTORY("dv4l", videoDV4L);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// videoDV4L
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
videoDV4L :: videoDV4L() : videoBase("dv4l"),
|
||||
m_raw(NULL),
|
||||
m_decoder(NULL),
|
||||
m_parsed(false),
|
||||
m_quality(DV_QUALITY_BEST)
|
||||
{
|
||||
m_devicenum = -1;
|
||||
|
||||
int i=0;
|
||||
for(i=0; i<3; i++) {
|
||||
m_frame [i] = NULL;
|
||||
m_pitches[i] = 0;
|
||||
}
|
||||
|
||||
provide("dv");
|
||||
|
||||
dv_init(1, 1); // singleton?
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
videoDV4L :: ~videoDV4L(){
|
||||
close();
|
||||
if(m_haveVideo)stopTransfer();
|
||||
if(m_decoder!=NULL)dv_decoder_free(m_decoder);
|
||||
|
||||
dv_cleanup(); // singleton?
|
||||
}
|
||||
|
||||
|
||||
bool videoDV4L :: grabFrame(){
|
||||
/* this actually only transports the raw1394 stream
|
||||
* libiec will issue a callback when a frame is ready
|
||||
*/
|
||||
fd_set rfds;
|
||||
if(m_dvfd<0)return false;
|
||||
struct timeval sleep;
|
||||
sleep.tv_sec=0; sleep.tv_usec=10; /* 10us */
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(m_dvfd, &rfds);
|
||||
int rv = select(m_dvfd + 1, &rfds, NULL, NULL, &sleep);
|
||||
if(rv >= 0) {
|
||||
DEBUG_WHERE;
|
||||
if(FD_ISSET(m_dvfd, &rfds)) {
|
||||
raw1394_loop_iterate(m_raw);
|
||||
}
|
||||
} else {
|
||||
perror("select");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int videoDV4L::decodeFrame(unsigned char*data, int len) {
|
||||
DEBUG_WHERE;
|
||||
if(!m_parsed) {
|
||||
dv_parse_header(m_decoder, data);
|
||||
if(NULL==m_frame[0]) {
|
||||
int w=m_decoder->width;
|
||||
int h=m_decoder->height;
|
||||
|
||||
m_frame [0]=new uint8_t[w*h*3];
|
||||
m_pitches[0]=w*3;
|
||||
|
||||
lock();
|
||||
m_image.image.xsize=w;
|
||||
m_image.image.ysize=h;
|
||||
m_image.image.reallocate();
|
||||
unlock();
|
||||
}
|
||||
m_parsed=true;
|
||||
} else {
|
||||
dv_decode_full_frame(m_decoder, data,
|
||||
e_dv_color_rgb,
|
||||
m_frame,
|
||||
m_pitches);
|
||||
|
||||
lock();
|
||||
m_image.newimage=true;
|
||||
m_image.image.fromRGB(m_frame[0]);
|
||||
m_image.image.upsidedown=true;
|
||||
unlock();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int videoDV4L::iec_frame(
|
||||
unsigned char *data,
|
||||
int len,
|
||||
int complete,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
DEBUG_WHERE;
|
||||
// post("iec_frame: %x/%d\t%d\t%x", data, len, complete, arg);
|
||||
if(complete) {
|
||||
videoDV4L*dv4l=(videoDV4L*)arg;
|
||||
return dv4l->decodeFrame(data, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// openDevice
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
bool videoDV4L :: openDevice(gem::Properties&props){
|
||||
DEBUG_WHERE;
|
||||
if(m_raw)closeDevice();
|
||||
|
||||
// LATER think about multithreading issues
|
||||
// according to the manual: "it is not allowed to use the same handle in multiple threads"
|
||||
// http://www.dennedy.org/libraw1394/API-raw1394-new-handle.html
|
||||
m_raw=raw1394_new_handle();
|
||||
if(!m_raw) {
|
||||
error("unable to get raw1394 handle");
|
||||
return false;
|
||||
}
|
||||
|
||||
int num_pinf=MAX_PORTNUM;
|
||||
struct raw1394_portinfo*pinf=new struct raw1394_portinfo[num_pinf];
|
||||
|
||||
int ports = raw1394_get_port_info(m_raw, pinf, num_pinf);
|
||||
verbose(1, "DV4L: got %d ports", ports);
|
||||
|
||||
int devnum=m_devicenum;
|
||||
if (!m_devicename.empty())
|
||||
devnum=-1;
|
||||
|
||||
int i=0;
|
||||
for(i=0; i<ports; i++) {
|
||||
verbose(1, "port#%02d: %.*s", i, 32, pinf[i].name);
|
||||
if (devnum<0 && m_devicename==pinf[i].name) {
|
||||
devnum=i;
|
||||
/* we don't "break" for the nice verbose listing of ports */
|
||||
// break;
|
||||
}
|
||||
}
|
||||
delete[]pinf;
|
||||
|
||||
int nodes=raw1394_get_nodecount(m_raw);
|
||||
verbose(1, "DV4L: got %d nodes", nodes);
|
||||
|
||||
if(devnum>=ports){
|
||||
closeDevice();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(devnum<0) {
|
||||
if (!m_devicename.empty()){
|
||||
/* bad devicename given */
|
||||
closeDevice();
|
||||
return false;
|
||||
}
|
||||
|
||||
/* default device (?) */
|
||||
devnum=0;
|
||||
}
|
||||
|
||||
if(raw1394_set_port(m_raw, devnum)<0) {
|
||||
perror("raw1394_set_port");
|
||||
closeDevice();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_dvfd = raw1394_get_fd(m_raw);
|
||||
if(m_dvfd<0) {
|
||||
verbose(1, "DV4L: illegal filedescriptor");
|
||||
closeDevice();
|
||||
return false;
|
||||
}
|
||||
|
||||
verbose(1, "DV4L: successfully opened device %d", devnum);
|
||||
|
||||
setProperties(props);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// closeDevice
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
void videoDV4L :: closeDevice(void){
|
||||
DEBUG_WHERE;
|
||||
if(m_dvfd>=0) ::close(m_dvfd);m_dvfd=-1;
|
||||
if(m_raw) raw1394_destroy_handle(m_raw);m_raw=NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// startTransfer
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
bool videoDV4L :: startTransfer()
|
||||
{
|
||||
DEBUG_WHERE;
|
||||
m_image.newimage=0;
|
||||
m_image.image.data=0;
|
||||
m_image.image.xsize=720;
|
||||
m_image.image.ysize=576;
|
||||
m_image.image.setCsizeByFormat(m_reqFormat);
|
||||
m_image.image.reallocate();
|
||||
|
||||
if(NULL==m_raw)return false;
|
||||
|
||||
m_parsed=false;
|
||||
|
||||
if(m_decoder!=NULL)dv_decoder_free(m_decoder);m_decoder=NULL;
|
||||
|
||||
if (!(m_decoder=dv_decoder_new(true, true, true))){
|
||||
error("DV4L: unable to create DV-decoder...closing");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_decoder->quality=m_quality;
|
||||
verbose(1, "DV4L: DV decoding quality %d ", m_decoder->quality);
|
||||
|
||||
m_iec = iec61883_dv_fb_init(m_raw, iec_frame, this);
|
||||
if(NULL==m_iec) {
|
||||
error("DV4L: unable to initialize IEC grabber");
|
||||
stopTransfer();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(iec61883_dv_fb_start(m_iec, 63) < 0) {
|
||||
error("DV4L: iec61883_dv_fb_start failed");
|
||||
stopTransfer();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
DEBUG_WHERE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// stopTransfer
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
bool videoDV4L :: stopTransfer()
|
||||
{
|
||||
DEBUG_WHERE;
|
||||
/* close the dv4l device and dealloc buffer */
|
||||
/* terminate thread if there is one */
|
||||
//stopThread(100);
|
||||
|
||||
if(m_iec) {
|
||||
iec61883_dv_fb_stop(m_iec);
|
||||
}
|
||||
|
||||
if(m_decoder) {
|
||||
dv_decoder_free(m_decoder);
|
||||
|
||||
m_decoder=NULL;
|
||||
}
|
||||
|
||||
int i=0;
|
||||
for(i=0; i<3; i++) {
|
||||
if(m_frame[i]) delete[]m_frame[i]; m_frame[i] = NULL;
|
||||
m_pitches[i] = 0;
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
/*
|
||||
bool videoDV4L :: setDevice(const std::string name){
|
||||
// setting device by name not yet supported
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
bool videoDV4L :: setColor(int format){
|
||||
if (format<=0)return false;
|
||||
m_reqFormat=format;
|
||||
lock();
|
||||
m_image.image.setCsizeByFormat(m_reqFormat);
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
//
|
||||
// Set the quality for DV decoding
|
||||
//
|
||||
/////////////////////////////////////////
|
||||
bool videoDV4L :: setQuality(int quality){
|
||||
if (quality<DV_QUALITY_FASTEST)return -1;
|
||||
if (quality>DV_QUALITY_BEST)return -1;
|
||||
m_quality=quality;
|
||||
|
||||
if(m_decoder) {
|
||||
dv_set_quality(m_decoder, m_quality);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::string> videoDV4L::enumerate() {
|
||||
std::vector<std::string> result;
|
||||
|
||||
raw1394handle_t handle=m_raw;
|
||||
if(NULL==m_raw) {
|
||||
handle=raw1394_new_handle();
|
||||
}
|
||||
|
||||
if(NULL==handle)return result;
|
||||
|
||||
int num_pinf=MAX_PORTNUM;
|
||||
struct raw1394_portinfo*pinf=new struct raw1394_portinfo[num_pinf];
|
||||
|
||||
int ports = raw1394_get_port_info(handle, pinf, num_pinf);
|
||||
int i=0;
|
||||
for(i=0; i<ports; i++) {
|
||||
result.push_back(pinf[i].name);
|
||||
}
|
||||
delete[]pinf;
|
||||
|
||||
if(NULL==m_raw) {
|
||||
raw1394_destroy_handle(handle);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool videoDV4L::enumProperties(gem::Properties&readable,
|
||||
gem::Properties&writeable) {
|
||||
gem::any typ;
|
||||
|
||||
readable.clear();
|
||||
writeable.clear();
|
||||
|
||||
typ=DV_QUALITY_BEST;
|
||||
writeable.set("quality", typ);
|
||||
|
||||
typ=1; // readables are all boolean
|
||||
readable.set("PAL", typ);
|
||||
readable.set("is_color", typ);
|
||||
readable.set("50_fields", typ);
|
||||
readable.set("normal", typ);
|
||||
readable.set("wide", typ);
|
||||
readable.set("letterbox", typ);
|
||||
readable.set("progressive", typ);
|
||||
|
||||
typ=0; // quality
|
||||
readable.set("quality", typ);
|
||||
|
||||
typ=0; // timestamp is a big number
|
||||
readable.set("timestamp", typ);
|
||||
|
||||
typ=std::string("YYYY-MM-DD hh:mm:ss"); // format of datetime string
|
||||
readable.set("recording_datetime", typ);
|
||||
|
||||
return true;
|
||||
}
|
||||
void videoDV4L::getProperties(gem::Properties&props) {
|
||||
std::vector<std::string>keys=props.keys();
|
||||
int i;
|
||||
|
||||
#if 0
|
||||
/* get properties without decoder */
|
||||
for(i=0; i<keys.size(); i++) {
|
||||
std::string key=keys[i];
|
||||
if(0) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* get properties that need decoder */
|
||||
if(m_decoder) {
|
||||
|
||||
for(i=0; i<keys.size(); i++) {
|
||||
std::string key=keys[i];
|
||||
if (0) {
|
||||
} else if("quality"==key) {
|
||||
props.set(key, m_decoder->quality);
|
||||
|
||||
|
||||
// return value: <0 unknown, 0 no, >0 yes
|
||||
} else if("PAL"==key) {
|
||||
props.set(key, dv_is_PAL(m_decoder));
|
||||
} else if("is_color"==key) {
|
||||
props.set(key, dv_frame_is_color(m_decoder));
|
||||
} else if("50_fields"==key) {
|
||||
props.set(key, dv_system_50_fields(m_decoder));
|
||||
} else if("normal"==key) {
|
||||
props.set(key, dv_format_normal(m_decoder));
|
||||
} else if("wide"==key) {
|
||||
props.set(key, dv_format_wide(m_decoder));
|
||||
} else if("letterbox"==key) {
|
||||
props.set(key, dv_format_letterbox(m_decoder));
|
||||
} else if("progressive"==key) {
|
||||
props.set(key, dv_is_progressive(m_decoder));
|
||||
|
||||
// return value: 0 not-present, >0 ok
|
||||
} else if("timestamp"==key) {
|
||||
// int dv_get_timestamp (dv_decoder_t *dv, char *tstprt);
|
||||
// int dv_get_timestamp_int (dv_decoder_t *dv, int *timestamp);
|
||||
|
||||
int ts[4];
|
||||
if(dv_get_timestamp_int (m_decoder, ts)>0) {
|
||||
double t=((ts[0]*60+ts[1])*60+ts[2])+ts[3]/100;
|
||||
props.set(key, t);
|
||||
}
|
||||
} else if("recording_datetime"==key) {
|
||||
// int dv_get_recording_datetime (dv_decoder_t *dv, char *dtptr);
|
||||
// int dv_get_recording_datetime_tm (dv_decoder_t *dv, struct tm *rec_dt);
|
||||
|
||||
char dt_str[40];
|
||||
char*dtptr=dt_str;
|
||||
if(dv_get_recording_datetime (m_decoder, dtptr)>0) {
|
||||
dt_str[39]=0; // just in case
|
||||
props.set(key, std::string(dt_str));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
void videoDV4L::setProperties(gem::Properties&props) {
|
||||
double d;
|
||||
if(props.get("quality", d)) {
|
||||
int quality=static_cast<int>(d);
|
||||
if (quality>=DV_QUALITY_FASTEST && quality<=DV_QUALITY_BEST) {
|
||||
m_quality=quality;
|
||||
|
||||
if(m_decoder) {
|
||||
dv_set_quality(m_decoder, m_quality);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#else // ! HAVE_DV
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// videoDV4L without DV-support
|
||||
//
|
||||
videoDV4L :: videoDV4L() : videoBase("")
|
||||
{ }
|
||||
videoDV4L :: ~videoDV4L()
|
||||
{ }
|
||||
#endif // HAVE_DV
|
Loading…
Add table
Add a link
Reference in a new issue