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

Revision 12912, 10.2 kB (checked in by robert, 2 years ago)

Added support for using GL_UNPACK_ROW_LENGTH in conjunction with texture's + osg::Image via new RowLength?
parameter in osg::Image. To support this Image::setData(..) now has a new optional rowLength parameter which
defaults to 0, which provides the original behaviour, Image::setRowLength(int) and int Image::getRowLength() are also provided.

With the introduction of RowLength? support in osg::Image it is now possible to create a sub image where
the t size of the image are smaller than the row length, useful for when you have a large image on the CPU
and which to use a small portion of it on the GPU. However, when these sub images are created the data
within the image is no longer contiguous so data access can no longer assume that all the data is in
one block. The new method Image::isDataContiguous() enables the user to check whether the data is contiguous,
and if not one can either access the data row by row using Image::data(column,row,image) accessor, or use the
new Image::DataIterator? for stepping through each block on memory assocatied with the image.

To support the possibility of non contiguous osg::Image usage of image objects has had to be updated to
check DataContiguous? and handle the case or use access via the DataIerator? or by row by row. To achieve
this a relatively large number of files has had to be modified, in particular the texture classes and
image plugins that doing writing.

  • 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.