- 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
313 lines
7.4 KiB
C++
313 lines
7.4 KiB
C++
////////////////////////////////////////////////////////
|
|
//
|
|
// GEM - Graphics Environment for Multimedia
|
|
//
|
|
// zmoelnig@iem.kug.ac.at
|
|
//
|
|
// Implementation file
|
|
//
|
|
// Copyright (c) 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
|
|
#ifdef HAVE_LIBVLC
|
|
|
|
#include <stdio.h>
|
|
#ifdef _MSC_VER
|
|
# define snprintf _snprintf
|
|
#endif
|
|
|
|
#include "videoVLC.h"
|
|
#include "plugins/PluginFactory.h"
|
|
|
|
#include "Gem/Exception.h"
|
|
#include "Gem/RTE.h"
|
|
|
|
#define MAXVLCSTRING 1024
|
|
|
|
using namespace gem::plugins;
|
|
|
|
#if 0
|
|
# define LOCK(x) post("%04d\t%s LOCK", __LINE__, __FUNCTION__), x.unlock(), post("%04d\t%s LOCKed", __LINE__, __FUNCTION__)
|
|
# define UNLOCK(x) post("%04d\t%s UNLOCK", __LINE__, __FUNCTION__), x.unlock(), post("%04d\t%s UNLOCKed", __LINE__, __FUNCTION__)
|
|
#else
|
|
# define LOCK(x) x.lock()
|
|
# define UNLOCK(x) x.unlock()
|
|
#endif
|
|
|
|
REGISTER_VIDEOFACTORY("vlc", videoVLC);
|
|
|
|
videoVLC::videoVLC(void) :
|
|
m_name(std::string("vlc")),
|
|
m_type(0),
|
|
m_instance(NULL),
|
|
m_mediaplayer(NULL)
|
|
{
|
|
const char * const vlc_args[] = {
|
|
// "--plugin-path=c:\\program files\\videolan\\vlc\\plugins",
|
|
"-I", "dummy", /* Don't use any interface */
|
|
"--ignore-config", /* Don't use VLC's config */
|
|
"--quiet",
|
|
// "--sout=#transcode{vcodec=RV24,acodec=s16l}:smem",
|
|
};
|
|
m_instance=libvlc_new (sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);
|
|
if(!m_instance) {
|
|
throw(GemException("couldn't initialize libVLC"));
|
|
}
|
|
|
|
m_pixBlock.image.xsize = 64;
|
|
m_pixBlock.image.ysize = 64;
|
|
m_pixBlock.image.setCsizeByFormat(GL_RGBA);
|
|
m_pixBlock.image.reallocate();
|
|
}
|
|
|
|
videoVLC::~videoVLC(void) {
|
|
if(m_instance)
|
|
libvlc_release(m_instance);
|
|
|
|
}
|
|
void videoVLC::close(void) {
|
|
if(m_mediaplayer)
|
|
libvlc_media_player_release(m_mediaplayer);
|
|
m_mediaplayer=NULL;
|
|
}
|
|
|
|
bool videoVLC::open(gem::Properties&props) {
|
|
if(m_mediaplayer)close();
|
|
setProperties(props);
|
|
|
|
|
|
if(m_devname.empty())
|
|
return false;
|
|
|
|
libvlc_media_t*media = libvlc_media_new_location (m_instance, m_devname.c_str());
|
|
if(!media)
|
|
media = libvlc_media_new_path (m_instance, m_devname.c_str());
|
|
|
|
if(!media)
|
|
return false;
|
|
|
|
|
|
char buf[MAXVLCSTRING];
|
|
|
|
libvlc_media_add_option(media,":noaudio");
|
|
libvlc_media_add_option(media,":no-video-title-show");
|
|
|
|
|
|
int w=m_pixBlock.image.xsize;
|
|
int h=m_pixBlock.image.ysize;
|
|
|
|
|
|
std::vector<std::string>keys=props.keys();
|
|
unsigned int i;
|
|
for(i=0; i<keys.size(); i++) {
|
|
std::string key=keys[i];
|
|
double d;
|
|
std::string s;
|
|
buf[0]=0;
|
|
if(0) {}
|
|
else if("width"==key) {
|
|
if(props.get(key, d)&&(d>0))
|
|
w=d;
|
|
} else if("height"==key) {
|
|
if(props.get(key, d)&&(d>0))
|
|
h=d;
|
|
} else {
|
|
gem::Properties::PropertyType type = props.type(key);
|
|
switch(type) {
|
|
case gem::Properties::NONE:
|
|
snprintf(buf, MAXVLCSTRING, ":%s", key.c_str());
|
|
break;
|
|
case gem::Properties::DOUBLE:
|
|
if(props.get(key, d)) {
|
|
snprintf(buf, MAXVLCSTRING, ":%s=%g", key.c_str(), d);
|
|
}
|
|
break;
|
|
case gem::Properties::STRING:
|
|
if(props.get(key, s)) {
|
|
/* need to find an option that actually takes strings, so i can test this with spaces */
|
|
snprintf(buf, MAXVLCSTRING, ":%s=%s", key.c_str(), s.c_str());
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if(0!=buf[0]) {
|
|
buf[MAXVLCSTRING-1]=0;
|
|
//post("vlc-option: '%s'", buf);
|
|
libvlc_media_add_option(media,buf);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
m_pixBlock.image.xsize = w;
|
|
m_pixBlock.image.ysize = h;
|
|
|
|
m_pixBlock.image.setCsizeByFormat(GL_RGBA);
|
|
m_pixBlock.image.reallocate();
|
|
m_pixBlock.image.setWhite();
|
|
|
|
|
|
|
|
|
|
|
|
m_mediaplayer=libvlc_media_player_new_from_media(media);
|
|
libvlc_media_release(media);
|
|
|
|
libvlc_video_set_callbacks(m_mediaplayer,
|
|
lockCB,
|
|
unlockCB,
|
|
NULL,
|
|
this);
|
|
|
|
libvlc_video_set_format(m_mediaplayer,
|
|
"RGBA",
|
|
m_pixBlock.image.xsize,
|
|
m_pixBlock.image.ysize,
|
|
m_pixBlock.image.xsize*m_pixBlock.image.csize);
|
|
return true;
|
|
}
|
|
|
|
pixBlock*videoVLC::getFrame(void) {
|
|
LOCK(m_mutex);
|
|
return &m_pixBlock;
|
|
}
|
|
|
|
void videoVLC::releaseFrame(void) {
|
|
// post("release frame");
|
|
UNLOCK(m_mutex);
|
|
}
|
|
|
|
std::vector<std::string>videoVLC::enumerate(void) {
|
|
std::vector<std::string>result;
|
|
result.push_back("vlc");
|
|
return result;
|
|
}
|
|
|
|
bool videoVLC::setDevice(int ID) {
|
|
m_devname.clear();
|
|
return false;
|
|
}
|
|
bool videoVLC::setDevice(std::string device) {
|
|
m_devname=device;
|
|
return true;
|
|
}
|
|
bool videoVLC::enumProperties(gem::Properties&readable,
|
|
gem::Properties&writeable) {
|
|
readable.clear();
|
|
writeable.clear();
|
|
|
|
writeable.set("width", m_pixBlock.image.xsize); readable.set("width", m_pixBlock.image.xsize);
|
|
writeable.set("height", m_pixBlock.image.ysize); readable.set("height", m_pixBlock.image.ysize);
|
|
return false;
|
|
}
|
|
void videoVLC::setProperties(gem::Properties&props) {
|
|
int width=-1;
|
|
int height=-1;
|
|
|
|
m_props=props;
|
|
|
|
double d;
|
|
if(props.get("width", d)) {
|
|
if(d>0)
|
|
width = d;
|
|
}
|
|
if(props.get("height", d)) {
|
|
if(d>0)
|
|
height=d;
|
|
}
|
|
|
|
if(!m_mediaplayer) {
|
|
if(width>0)
|
|
m_pixBlock.image.xsize=width;
|
|
if(height>0)
|
|
m_pixBlock.image.ysize=height;
|
|
} else {
|
|
// changes will take effect with next restart
|
|
}
|
|
}
|
|
|
|
|
|
void videoVLC::getProperties(gem::Properties&props) {
|
|
std::vector<std::string>keys=props.keys();
|
|
double d;
|
|
int i;
|
|
|
|
for(i=0; i<keys.size(); i++) {
|
|
if("width"==keys[i]) {
|
|
props.set(keys[i], m_pixBlock.image.xsize);
|
|
}
|
|
if("height"==keys[i]) {
|
|
props.set(keys[i], m_pixBlock.image.ysize);
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<std::string>videoVLC::dialogs(void) {
|
|
std::vector<std::string>result;
|
|
return result;
|
|
}
|
|
bool videoVLC::provides(const std::string name) {
|
|
return (name==m_name);
|
|
}
|
|
std::vector<std::string>videoVLC::provides(void) {
|
|
std::vector<std::string>result;
|
|
result.push_back(m_name);
|
|
return result;
|
|
}
|
|
const std::string videoVLC::getName(void) {
|
|
return m_name;
|
|
}
|
|
|
|
|
|
bool videoVLC::start(void) {
|
|
int ret=-1;
|
|
if(m_mediaplayer) {
|
|
int ret=libvlc_media_player_play(m_mediaplayer);
|
|
}
|
|
return (0!=ret);
|
|
}
|
|
bool videoVLC::stop (void) {
|
|
if(!m_mediaplayer)
|
|
return false;
|
|
libvlc_media_player_stop(m_mediaplayer);
|
|
return true;
|
|
}
|
|
|
|
void*videoVLC::lockFrame(void**plane ) {
|
|
LOCK(m_mutex);
|
|
*plane=m_pixBlock.image.data;
|
|
// post("prepareFrame %p @ %p --> %p", *plane, plane, m_pixBlock.image.data);
|
|
|
|
return NULL;
|
|
}
|
|
void videoVLC::unlockFrame(void*picture, void*const*plane) {
|
|
// post("processFrame %p\t%p", picture, *plane);
|
|
m_pixBlock.newimage=true;
|
|
m_pixBlock.image.upsidedown=true;
|
|
UNLOCK(m_mutex);
|
|
}
|
|
void*videoVLC::lockCB(void*opaque, void**plane ) {
|
|
// post(" lockCB: %p", opaque);
|
|
videoVLC*obj=(videoVLC*)opaque;
|
|
if(obj)
|
|
return obj->lockFrame(plane);
|
|
|
|
return NULL;
|
|
}
|
|
void videoVLC::unlockCB(void*opaque, void*picture, void*const*plane) {
|
|
// post(" unlockCB: %p", opaque);
|
|
videoVLC*obj=(videoVLC*)opaque;
|
|
if(obj)
|
|
obj->unlockFrame(picture, plane);
|
|
}
|
|
void videoVLC::displayCB(void*opaque, void*picture) {
|
|
// post("displayCB: %p -> %p", opaque, picture);
|
|
videoVLC*obj=(videoVLC*)opaque;
|
|
}
|
|
|
|
#endif /* HAVE_LIBVLC */
|