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

Revision 13041, 10.0 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • 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            imageStream->setImage(width,height,1,
196                              GL_RGB,
197                              pixelFormat,GL_UNSIGNED_BYTE,
198                              (unsigned char *)data,
199                              osg::Image::NO_DELETE,
200                              1);
201
202            imageStream->_ready = true;
203        }
204
205
206        xine_t*                 _xine;
207
208        xine_video_port_t*      _vo;
209        xine_audio_port_t*      _ao;
210
211        rgbout_visual_info_t*   _visual;
212        xine_stream_t*          _stream;
213        xine_event_queue_t*     _event_queue;
214        bool                    _ready;
215        float                   _volume;
216
217    protected:
218
219
220        virtual ~XineImageStream()
221        {
222            OSG_INFO<<"Killing XineImageStream"<<std::endl;
223            close();
224            OSG_INFO<<"Closed XineImageStream"<<std::endl;
225        }
226
227        void close()
228        {
229
230            OSG_INFO<<"XineImageStream::close()"<<std::endl;
231
232            if (_stream)
233            {
234                  OSG_INFO<<"  Closing stream"<<std::endl;
235
236                  xine_close(_stream);
237
238                  OSG_INFO<<"  Disposing stream"<<std::endl;
239
240                  xine_dispose(_stream);
241                  _stream = 0;
242            }
243
244
245            if (_event_queue)
246            {
247                _event_queue = 0;
248            }
249
250            if (_ao)
251            {
252               OSG_INFO<<"  Closing audio driver"<<std::endl;
253
254                xine_close_audio_driver(_xine, _ao);
255
256                _ao = 0;
257            }
258
259            if (_vo)
260            {
261               OSG_INFO<<"  Closing video driver"<<std::endl;
262
263                xine_close_video_driver(_xine, _vo);
264
265                _vo = 0;
266            }
267
268           OSG_INFO<<"closed XineImageStream "<<std::endl;
269
270        }
271
272
273        static void event_listener(void *user_data, const xine_event_t *event)
274        {
275            XineImageStream* xis = reinterpret_cast<XineImageStream*>(user_data);
276            switch(event->type)
277            {
278            case XINE_EVENT_UI_PLAYBACK_FINISHED:
279                if (xis->getLoopingMode()==LOOPING)
280                {
281                    //rewind();
282                    xine_play(xis->_stream, 0, 0);
283                }
284                break;
285            }
286        }
287
288};
289
290}
291
292class ReaderWriterXine : public osgDB::ReaderWriter
293{
294    public:
295
296        ReaderWriterXine()
297        {
298            supportsExtension("avi","");
299            supportsExtension("db","");
300            supportsExtension("ogv","");
301            supportsExtension("flv","");
302            supportsExtension("mov","");
303            supportsExtension("m4v","");
304            supportsExtension("mpg","Mpeg movie format");
305            supportsExtension("mpv","Mpeg movie format");
306            supportsExtension("wmv","");
307            supportsExtension("xine","Xine plugin Pseduo plugin");
308
309            _xine = xine_new();
310
311            const char* user_home = xine_get_homedir();
312            if(user_home)
313            {
314                std::string configFile(std::string(user_home)+"/.xine/config");
315                xine_config_load(_xine, configFile.c_str());
316            }
317
318            xine_init(_xine);
319
320            register_rgbout_plugin(_xine);
321        }
322
323        virtual ~ReaderWriterXine()
324        {
325            OSG_INFO<<"~ReaderWriterXine()"<<std::endl;
326
327            if (_xine) xine_exit(_xine);
328            _xine = NULL;
329        }
330
331        virtual const char* className() const { return "Xine ImageStream Reader"; }
332
333        virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
334        {
335            std::string ext = osgDB::getLowerCaseFileExtension(file);
336            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
337
338            std::string fileName;
339            if (ext=="xine")
340            {
341                fileName = osgDB::findDataFile( osgDB::getNameLessExtension(file), options);
342                OSG_INFO<<"Xine stipped filename = "<<fileName<<std::endl;
343            }
344            else
345            {
346                fileName = osgDB::findDataFile( file, options );
347                if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
348            }
349
350            OSG_INFO<<"ReaderWriterXine::readImage "<< file<< std::endl;
351
352            osg::ref_ptr<osgXine::XineImageStream> imageStream = new osgXine::XineImageStream();
353
354            if (!imageStream->open(_xine, fileName)) return ReadResult::FILE_NOT_HANDLED;
355
356            return imageStream.release();
357        }
358
359    protected:
360        xine_t*             _xine;
361
362
363};
364
365// now register with Registry to instantiate the above
366// reader/writer.
367REGISTER_OSGPLUGIN(xine, ReaderWriterXine)
Note: See TracBrowser for help on using the browser.