root/OpenSceneGraph/trunk/src/osgPlugins/xine/ReaderWriterXine.cpp @ 12262

Revision 12262, 10.9 kB (checked in by robert, 3 years ago)

Added m4v as a handled movie file extension

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// (C) Robert Osfield, Feb 2004.
2// GPL'd.
3
4#include <osg/ImageStream>
5#include <osg/Notify>
6#include <osg/Geode>
7#include <osg/GL>
8#include <osg/Timer>
9
10#include <osgDB/Registry>
11#include <osgDB/FileNameUtils>
12#include <osgDB/FileUtils>
13
14#include <xine.h>
15#include <xine/xineutils.h>
16#include <xine/video_out.h>
17
18#include "video_out_rgb.h"
19
20namespace osgXine
21{
22
23class XineImageStream : public osg::ImageStream
24{
25    public:
26        XineImageStream():
27            _xine(0),
28            _vo(0),
29            _ao(0),
30            _visual(0),
31            _stream(0),
32            _event_queue(0),
33            _ready(false),
34            _volume(-1.0)
35        {
36            setOrigin(osg::Image::TOP_LEFT);
37        }
38
39        /** Copy constructor using CopyOp to manage deep vs shallow copy. */
40        XineImageStream(const XineImageStream& image,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
41            ImageStream(image,copyop) {}
42
43        META_Object(osgXine,XineImageStream);
44       
45        void setVolume(float volume)
46        {
47            _volume = osg::minimum(osg::maximum(volume,0.0f),1.0f);
48            if (_stream)
49            {
50                xine_set_param(_stream, XINE_PARAM_AUDIO_VOLUME, static_cast<int>(_volume*100.0f));
51                OSG_NOTICE<<"Setting volume "<<_volume<<std::endl;
52            }
53        }
54       
55        float getVolume() const
56        {
57            return _volume;
58        }
59
60        bool open(xine_t* xine, const std::string& filename)
61        {
62            if (filename==getFileName()) return true;
63           
64            _xine = xine;
65       
66            // create visual
67            rgbout_visual_info_t* visual = new rgbout_visual_info_t;
68            visual->levels = PXLEVEL_ALL;
69            visual->format = PX_RGB32;
70            visual->user_data = this;
71            visual->callback = my_render_frame;
72
73            // set up video driver
74            _vo = xine_open_video_driver(_xine, "rgb", XINE_VISUAL_TYPE_RGBOUT, (void*)visual);
75
76            // set up audio driver
77            char* audio_driver = getenv("OSG_XINE_AUDIO_DRIVER");
78            _ao = audio_driver ? xine_open_audio_driver(_xine, audio_driver, NULL) : xine_open_audio_driver(_xine, "auto", NULL);
79
80            if (!_vo)
81            {
82                OSG_NOTICE<<"XineImageStream::open() : Failed to create video driver"<<std::endl;
83                return false;
84            }
85           
86
87            // set up stream
88            _stream = xine_stream_new(_xine, _ao, _vo);
89           
90            if (_stream)
91            {
92                if (_volume < 0.0)
93                {
94                    _volume = static_cast<float>(xine_get_param(_stream, XINE_PARAM_AUDIO_VOLUME))/100.0f;
95                }
96                else
97                {
98                    setVolume(_volume);
99                }
100            }
101
102            _event_queue = xine_event_new_queue(_stream);
103            xine_event_create_listener_thread(_event_queue, event_listener, this);
104
105            int result = xine_open(_stream, filename.c_str());
106           
107            if (result==0)
108            {
109                OSG_INFO<<"XineImageStream::open() : Could not ready movie file."<<std::endl;
110                close();
111                return false;
112            }
113           
114           
115            _ready = false;
116           
117            int width = xine_get_stream_info(_stream,XINE_STREAM_INFO_VIDEO_WIDTH);
118            int height = xine_get_stream_info(_stream,XINE_STREAM_INFO_VIDEO_HEIGHT);
119            allocateImage(width,height,1,GL_RGB,GL_UNSIGNED_BYTE,1);
120
121            OSG_INFO<<"XineImageStream::open() size "<<width<<" "<<height<<std::endl;
122
123            // play();
124           
125            return true;
126
127        }
128
129        virtual void play()
130        {
131            if (_status!=PLAYING && _stream)
132            {
133                if (_status==PAUSED)
134                {
135                    xine_set_param (_stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
136                    _status=PLAYING;
137                }
138                else
139                {
140                    OSG_INFO<<"XineImageStream::play()"<<std::endl;
141                    if (xine_play(_stream, 0, 0))
142                    {
143                        while (!_ready)
144                        {
145                            OSG_INFO<<"   waiting..."<<std::endl;
146                            OpenThreads::Thread::microSleep(10000);
147                        }
148
149                        _status=PLAYING;
150
151                    }
152                    else
153                    {
154                        OSG_NOTICE<<"Error!!!"<<std::endl;
155                    }
156                }
157            }
158        }
159
160        virtual void pause()
161        {
162            if (_status==PAUSED || _status==INVALID) return;
163
164            _status=PAUSED;
165           
166            if (_stream)
167            {
168                xine_set_param (_stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
169            }
170        }
171
172        virtual void rewind()
173        {
174            if (_status==INVALID) return;
175
176            _status=REWINDING;
177            if (_stream)
178            {
179                OSG_INFO<<"Warning::XineImageStream::rewind() - rewind disabled at present."<<std::endl;
180                //xine_trick_mode(_stream,XINE_TRICK_MODE_FAST_REWIND,0);
181            }
182        }
183
184        virtual void quit(bool /*waitForThreadToExit*/ = true)
185        {
186            close();
187        }
188
189        static void my_render_frame(uint32_t width, uint32_t height, void* data, void* userData)
190        {
191            XineImageStream* imageStream = (XineImageStream*) userData;
192
193            GLenum pixelFormat = GL_BGRA;
194
195        #if 0   
196            if (!imageStream->_ready)
197            {
198                imageStream->allocateImage(width,height,1,pixelFormat,GL_UNSIGNED_BYTE,1);
199                imageStream->setInternalTextureFormat(GL_RGBA);
200            }
201
202            osg::Timer_t start_tick = osg::Timer::instance()->tick();
203
204            memcpy(imageStream->data(),data,imageStream->getTotalSizeInBytes());
205
206            OSG_INFO<<"image memcpy size="<<imageStream->getTotalSizeInBytes()<<" time="<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
207
208
209            imageStream->dirty();
210        #else
211             imageStream->setImage(width,height,1,
212                              GL_RGB,
213                              pixelFormat,GL_UNSIGNED_BYTE,
214                              (unsigned char *)data,
215                              osg::Image::NO_DELETE,
216                              1);
217        #endif
218            imageStream->_ready = true;
219        }
220
221
222        xine_t*                 _xine;
223
224        xine_video_port_t*      _vo;
225        xine_audio_port_t*      _ao;
226
227        rgbout_visual_info_t*   _visual;
228        xine_stream_t*          _stream;
229        xine_event_queue_t*     _event_queue;
230        bool                    _ready;
231        float                   _volume;
232
233    protected:
234
235
236        virtual ~XineImageStream()
237        {
238            OSG_INFO<<"Killing XineImageStream"<<std::endl;
239            close();
240            OSG_INFO<<"Closed XineImageStream"<<std::endl;
241        }
242
243        void close()
244        {
245
246            OSG_INFO<<"XineImageStream::close()"<<std::endl;
247
248            if (_stream)
249            {
250                  OSG_INFO<<"  Closing stream"<<std::endl;
251               
252                  xine_close(_stream);
253
254                  OSG_INFO<<"  Disposing stream"<<std::endl;
255
256                  xine_dispose(_stream);
257                  _stream = 0;
258            }
259
260
261            if (_event_queue)
262            {
263                _event_queue = 0;
264            }
265
266            if (_ao)
267            {
268               OSG_INFO<<"  Closing audio driver"<<std::endl;
269
270                xine_close_audio_driver(_xine, _ao); 
271               
272                _ao = 0;
273            }
274           
275            if (_vo)
276            {
277               OSG_INFO<<"  Closing video driver"<<std::endl;
278
279                xine_close_video_driver(_xine, _vo); 
280               
281                _vo = 0;
282            }
283
284           OSG_INFO<<"closed XineImageStream "<<std::endl;
285
286        }
287
288
289        static void event_listener(void *user_data, const xine_event_t *event)
290        {
291            XineImageStream* xis = reinterpret_cast<XineImageStream*>(user_data);
292            switch(event->type)
293            {
294            case XINE_EVENT_UI_PLAYBACK_FINISHED:
295                if (xis->getLoopingMode()==LOOPING)
296                {
297                    //rewind();
298                    xine_play(xis->_stream, 0, 0);
299                }
300                break;
301            }
302        }
303
304};
305
306}
307
308class ReaderWriterXine : public osgDB::ReaderWriter
309{
310    public:
311
312        ReaderWriterXine()
313        {
314            supportsExtension("avi","");
315            supportsExtension("db","");
316            supportsExtension("ogv","");
317            supportsExtension("flv","");
318            supportsExtension("mov","");
319            supportsExtension("m4v","");
320            supportsExtension("mpg","Mpeg movie format");
321            supportsExtension("mpv","Mpeg movie format");
322            supportsExtension("wmv","");
323            supportsExtension("xine","Xine plugin Pseduo plugin");
324       
325            _xine = xine_new();
326
327            const char* user_home = xine_get_homedir();
328            if(user_home)
329            {
330                std::string configFile(std::string(user_home)+"/.xine/config");
331                xine_config_load(_xine, configFile.c_str());
332            }
333
334            xine_init(_xine);
335           
336            register_rgbout_plugin(_xine);
337        }
338     
339        virtual ~ReaderWriterXine()
340        {
341            OSG_INFO<<"~ReaderWriterXine()"<<std::endl;
342       
343            if (_xine) xine_exit(_xine);
344            _xine = NULL;
345        }
346       
347        virtual const char* className() const { return "Xine ImageStream Reader"; }
348
349        virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
350        {
351            std::string ext = osgDB::getLowerCaseFileExtension(file);
352            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
353           
354            std::string fileName;
355            if (ext=="xine")
356            {
357                fileName = osgDB::findDataFile( osgDB::getNameLessExtension(file), options);
358                OSG_INFO<<"Xine stipped filename = "<<fileName<<std::endl;
359            }
360            else
361            {
362                fileName = osgDB::findDataFile( file, options );
363                if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
364            }
365
366            OSG_INFO<<"ReaderWriterXine::readImage "<< file<< std::endl;
367
368            osg::ref_ptr<osgXine::XineImageStream> imageStream = new osgXine::XineImageStream();
369
370            if (!imageStream->open(_xine, fileName)) return ReadResult::FILE_NOT_HANDLED;
371
372            return imageStream.release();
373        }
374
375    protected:
376        xine_t*             _xine;
377
378
379};
380
381// now register with Registry to instantiate the above
382// reader/writer.
383REGISTER_OSGPLUGIN(xine, ReaderWriterXine)
Note: See TracBrowser for help on using the browser.