// (C) Robert Osfield, Feb 2004. // GPL'd. #include #include #include #include #include #include #include #include #include #include #include #include "video_out_rgb.h" namespace osgXine { class XineImageStream : public osg::ImageStream { public: XineImageStream(): _xine(0), _vo(0), _ao(0), _visual(0), _stream(0), _event_queue(0), _ready(false) {} /** Copy constructor using CopyOp to manage deep vs shallow copy. */ XineImageStream(const XineImageStream& image,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY): ImageStream(image,copyop) {} META_Object(osgXine,XineImageStream); bool open(xine_t* xine, const std::string& filename) { if (filename==getFileName()) return true; _xine = xine; // create visual rgbout_visual_info_t* visual = new rgbout_visual_info_t; visual->levels = PXLEVEL_ALL; visual->format = PX_RGB32; visual->user_data = this; visual->callback = my_render_frame; // set up video driver _vo = xine_open_video_driver(_xine, "rgb", XINE_VISUAL_TYPE_RGBOUT, (void*)visual); // set up audio driver char* audio_driver = getenv("OSG_XINE_AUDIO_DRIVER"); _ao = audio_driver ? xine_open_audio_driver(_xine, audio_driver, NULL) : xine_open_audio_driver(_xine, "auto", NULL); if (!_vo) { osg::notify(osg::NOTICE)<<"XineImageStream::open() : Failed to create video driver"<_ready) { imageStream->allocateImage(width,height,1,pixelFormat,GL_UNSIGNED_BYTE,1); imageStream->setInternalTextureFormat(GL_RGBA); } osg::Timer_t start_tick = osg::Timer::instance()->tick(); memcpy(imageStream->data(),data,imageStream->getTotalSizeInBytes()); osg::notify(osg::INFO)<<"image memcpy size="<getTotalSizeInBytes()<<" time="<delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<dirty(); #else imageStream->setImage(width,height,1, GL_RGB, pixelFormat,GL_UNSIGNED_BYTE, (unsigned char *)data, osg::Image::NO_DELETE, 1); #endif imageStream->_ready = true; } xine_t* _xine; xine_video_port_t* _vo; xine_audio_port_t* _ao; rgbout_visual_info_t* _visual; xine_stream_t* _stream; xine_event_queue_t* _event_queue; bool _ready; protected: virtual ~XineImageStream() { osg::notify(osg::INFO)<<"Killing XineImageStream"<(user_data); switch(event->type) { case XINE_EVENT_UI_PLAYBACK_FINISHED: if (xis->getLoopingMode()==LOOPING) { //rewind(); xine_play(xis->_stream, 0, 0); } break; } } }; } class ReaderWriterXine : public osgDB::ReaderWriter { public: ReaderWriterXine() { _xine = xine_new(); const char* user_home = xine_get_homedir(); if(user_home) { char* cfgfile = NULL; asprintf(&(cfgfile), "%s/.xine/config", user_home); xine_config_load(_xine, cfgfile); } xine_init(_xine); register_rgbout_plugin(_xine); } virtual ~ReaderWriterXine() { osg::notify(osg::INFO)<<"~ReaderWriterXine()"< imageStream = new osgXine::XineImageStream(); if (!imageStream->open(_xine, fileName)) return ReadResult::FILE_NOT_HANDLED; return imageStream.release(); } protected: xine_t* _xine; }; // now register with Registry to instantiate the above // reader/writer. osgDB::RegisterReaderWriterProxy g_readerWriter_Xine_Proxy;