//////////////////////////////////////////////////////// // // 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 #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::vectorkeys=props.keys(); unsigned int i; for(i=0; i0)) 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::vectorvideoVLC::enumerate(void) { std::vectorresult; 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::vectorkeys=props.keys(); double d; int i; for(i=0; ivideoVLC::dialogs(void) { std::vectorresult; return result; } bool videoVLC::provides(const std::string name) { return (name==m_name); } std::vectorvideoVLC::provides(void) { std::vectorresult; 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 */