Update to 2.0.0 tree from current Fremantle build
[opencv] / src / highgui / cvcap_xine.cpp
diff --git a/src/highgui/cvcap_xine.cpp b/src/highgui/cvcap_xine.cpp
new file mode 100644 (file)
index 0000000..8abf9b7
--- /dev/null
@@ -0,0 +1,847 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                        Intel License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000, Intel Corporation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of Intel Corporation may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+// Authors: Konstantin Dols <dols@ient.rwth-aachen.de>
+//          Mark Asbach <asbach@ient.rwth-aachen.de>
+//
+//          Institute of Communications Engineering
+//          RWTH Aachen University
+
+
+#include "_highgui.h"
+
+// required to enable some functions used here...
+#define XINE_ENABLE_EXPERIMENTAL_FEATURES
+
+#include <cv.h>
+#include <cassert>
+
+extern "C"
+{
+#include <xine.h>
+       //#include <xine/xineutils.h>
+
+       // forward declaration from <xine/xineutils.h>
+       const char *xine_get_homedir( void );
+}
+
+typedef struct CvCaptureAVI_XINE
+{
+       /// method call table
+       xine_t * xine;
+       xine_stream_t * stream;
+       xine_video_port_t * vo_port;
+
+       /// frame returned by xine_get_next_video_frame()
+       xine_video_frame_t xine_frame;
+
+       IplImage        * yuv_frame;
+       IplImage        * bgr_frame;
+
+       /// image dimansions of the input stream.
+       CvSize  size;
+
+       /// framenumber of the last frame received from xine_get_next_video_frame().
+       /// note: always keep this value updated !!!!
+       int     frame_number;
+
+       /// framerate of the opened stream
+       double  frame_rate;
+
+       /// duration of a frame in stream
+       double  frame_duration;
+
+       /// indicated if input is seekable
+       bool    seekable;
+
+}
+CvCaptureAVI_XINE;
+
+
+// 4:2:2 interleaved -> BGR
+static void icvYUY2toBGR( CvCaptureAVI_XINE * capture )
+{
+       uint8_t * v     = capture->xine_frame.data;
+       int offset;
+       for ( int y = 0; y < capture->yuv_frame->height; y++ )
+       {
+               offset  = y * capture->yuv_frame->widthStep;
+
+               for ( int x = 0; x < capture->yuv_frame->width; x++, offset += 3 )
+               {
+                       capture->yuv_frame->imageData[ offset + 1 ] = v[ 3 ];
+                       capture->yuv_frame->imageData[ offset + 2 ] = v[ 1 ];
+                       if ( x & 1 )
+                       {
+                               capture->yuv_frame->imageData[ offset ] = v[ 2 ];
+                               v += 4;
+                       }
+                       else
+                       {
+                               capture->yuv_frame->imageData[ offset ] = v[ 0 ];
+                       }
+               }
+       }
+
+       // convert to BGR
+       cvCvtColor( capture->yuv_frame, capture->bgr_frame, CV_YCrCb2BGR );
+}
+
+
+// 4:2:0 planary -> BGR
+static void icvYV12toBGR( CvCaptureAVI_XINE * capture )
+{
+       IplImage * yuv  = capture->yuv_frame;
+       int     w_Y     = capture->size.width;
+       int     h_Y     = capture->size.height;
+
+       int     w_UV    = w_Y >> 1;
+
+       int     size_Y  = w_Y * h_Y;
+       int     size_UV = size_Y / 4;
+
+       int     line    = yuv->widthStep;
+
+       uint8_t * addr_Y = capture->xine_frame.data;
+       uint8_t * addr_U = addr_Y + size_Y;
+       uint8_t * addr_V = addr_U + size_UV;
+
+       // YYYY..UU.VV. -> BGRBGRBGR...
+       for ( int y = 0; y < h_Y; y++ )
+       {
+               int offset = y * line;
+               for ( int x = 0; x < w_Y; x++, offset += 3 )
+               {
+                       /*
+                       if ( x&1 )
+                       {
+                               addr_U++; addr_V++;
+                       }
+                       */
+                       int one_zero = x & 1;
+                       addr_U += one_zero;
+                       addr_V += one_zero;
+
+                       yuv->imageData[ offset ] = *( addr_Y++ );
+                       yuv->imageData[ offset + 1 ] = *addr_U;
+                       yuv->imageData[ offset + 2 ] = *addr_V;
+               }
+
+               if ( y & 1 )
+               {
+                       addr_U -= w_UV;
+                       addr_V -= w_UV;
+               }
+       }
+
+       /* convert to BGR */
+       cvCvtColor( capture->yuv_frame, capture->bgr_frame, CV_YCrCb2BGR );
+}
+
+static void icvCloseAVI_XINE( CvCaptureAVI_XINE* capture )
+{
+       xine_free_video_frame( capture->vo_port, &capture->xine_frame );
+
+       if ( capture->yuv_frame ) cvReleaseImage( &capture->yuv_frame );
+       if ( capture->bgr_frame ) cvReleaseImage( &capture->bgr_frame );
+
+       xine_close( capture->stream );
+       //      xine_dispose( capture->stream );
+
+       if ( capture->vo_port ) xine_close_video_driver( capture->xine, capture->vo_port );
+
+       xine_exit( capture->xine );
+}
+
+
+/**
+ * CHECKS IF THE STREAM IN * capture IS SEEKABLE.
+**/
+static void icvCheckSeekAVI_XINE( CvCaptureAVI_XINE * capture )
+{
+       OPENCV_ASSERT ( capture,                        "icvCheckSeekAVI_XINE( CvCaptureAVI_XINE* )", "illegal capture");
+       OPENCV_ASSERT ( capture->stream,
+                        "icvCheckSeekAVI_XINE( CvCaptureAVI_XINE* )", "illegal capture->stream");
+       OPENCV_ASSERT ( capture->vo_port,
+                        "icvCheckSeekAVI_XINE( CvCaptureAVI_XINE* )", "illegal capture->vo_port");
+
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvCheckSeekAVI_XINE ... start\n" );
+#endif
+
+       // temp. frame for testing.
+       xine_video_frame_t tmp;
+       // try to seek to a future frame...
+       xine_play( capture->stream, 0, 300 ); /* 300msec */
+       // try to receive the frame...
+       xine_get_next_video_frame( capture->vo_port, &tmp );
+       // if the framenumber is still 0, we can't use the xine seek functionality
+       capture->seekable = ( tmp.frame_number != 0 );
+       // reset stream
+       xine_play( capture->stream, 0, 0 );
+       // release xine_frame
+       xine_free_video_frame( capture->vo_port, &tmp );
+
+#ifndef NDEBUG
+       if ( capture->seekable )
+               fprintf( stderr, "(DEBUG) icvCheckSeekAVI_XINE: Input is seekable, using XINE seek implementation.\n" );
+       else
+               fprintf( stderr, "(DEBUG) icvCheckSeekAVI_XINE: Input is NOT seekable, using fallback function.\n" );
+
+       fprintf( stderr, "(DEBUG) icvCheckSeekAVI_XINE ... end\n" );
+#endif
+}
+
+
+static int icvOpenAVI_XINE( CvCaptureAVI_XINE* capture, const char* filename )
+{
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvOpenAVI_XINE ... start\n" );
+#endif
+
+       char configfile[ 2048 ];
+
+       capture->xine = xine_new();
+       sprintf( configfile, "%s%s", xine_get_homedir(), "/.xine/config" );
+
+       xine_config_load( capture->xine, configfile );
+       xine_init( capture->xine );
+
+       xine_engine_set_param( capture->xine, 0, 0 );
+       capture->vo_port = xine_new_framegrab_video_port( capture->xine );
+       if ( capture->vo_port == NULL )
+       {
+               printf( "(ERROR)icvOpenAVI_XINE(): Unable to initialize video driver.\n" );
+               return 0;
+       }
+
+       capture->stream = xine_stream_new( capture->xine, NULL, capture->vo_port );
+
+       if ( !xine_open( capture->stream, filename ) )
+       {
+               printf( "(ERROR)icvOpenAVI_XINE(): Unable to open source '%s'\n", filename );
+               return 0;
+       }
+       // reset stream...
+       xine_play( capture->stream, 0, 0 );
+
+
+       // initialize some internals...
+       capture->frame_number = 0;
+
+       if ( !xine_get_next_video_frame( capture->vo_port, &capture->xine_frame ) )
+       {
+#ifndef NDEBUG
+               fprintf( stderr, "(DEBUG) icvOpenAVI_XINE ... failed!\n" );
+#endif
+               return 0;
+       }
+
+       capture->size = cvSize( capture->xine_frame.width, capture->xine_frame.height );
+       capture->yuv_frame = cvCreateImage( capture->size, IPL_DEPTH_8U, 3 );
+       capture->bgr_frame = cvCreateImage( capture->size, IPL_DEPTH_8U, 3 );
+
+       xine_free_video_frame( capture->vo_port, &capture->xine_frame );
+       capture->xine_frame.data[ 0 ] = 0;
+
+       icvCheckSeekAVI_XINE( capture );
+
+       capture->frame_duration = xine_get_stream_info( capture->stream, XINE_STREAM_INFO_FRAME_DURATION ) / 90.;
+       capture->frame_rate = 1000 / capture->frame_duration;
+
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) frame_duration = %f, framerate = %f\n", capture->frame_duration, capture->frame_rate );
+#endif
+
+       OPENCV_ASSERT ( capture->yuv_frame,
+                        "icvOpenAVI_XINE( CvCaptureAVI_XINE *, const char *)", "couldn't create yuv frame");
+
+       OPENCV_ASSERT ( capture->bgr_frame,
+                        "icvOpenAVI_XINE( CvCaptureAVI_XINE *, const char *)", "couldn't create bgr frame");
+
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvOpenAVI_XINE ... end\n" );
+#endif
+       return 1;
+}
+
+
+static int icvGrabFrameAVI_XINE( CvCaptureAVI_XINE* capture )
+{
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvGrabFrameAVI_XINE ... start\n" );
+#endif
+
+       OPENCV_ASSERT ( capture,
+                        "icvGrabFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture");
+       OPENCV_ASSERT ( capture->vo_port,
+                        "icvGrabFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture->vo_port");
+
+       int res = xine_get_next_video_frame( capture->vo_port, &capture->xine_frame );
+
+       /* always keep internal framenumber updated !!! */
+       if ( res ) capture->frame_number++;
+
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvGrabFrameAVI_XINE ... end\n" );
+#endif
+       return res;
+}
+
+
+static const IplImage* icvRetrieveFrameAVI_XINE( CvCaptureAVI_XINE* capture, int )
+{
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvRetrieveFrameAVI_XINE ... start\n" );
+#endif
+
+       OPENCV_ASSERT ( capture,
+                        "icvRetrieveFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture");
+       OPENCV_ASSERT ( capture->stream,
+                        "icvRetrieveFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture->stream");
+       OPENCV_ASSERT ( capture->vo_port,
+                        "icvRetrieveFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture->vo_port");
+
+       /* no frame grabbed yet? so let's do it now! */
+       int res = 0;
+       if ( capture->xine_frame.data == 0 )
+       {
+               res = icvGrabFrameAVI_XINE( capture );
+       }
+       else
+       {
+               res = 1;
+       }
+
+       if ( res )
+       {
+               switch ( capture->xine_frame.colorspace )
+               {
+                               case XINE_IMGFMT_YV12: icvYV12toBGR( capture );
+#ifndef NDEBUG
+                               printf( "(DEBUG)icvRetrieveFrameAVI_XINE: converted YV12 to BGR.\n" );
+#endif
+                               break;
+
+                               case XINE_IMGFMT_YUY2: icvYUY2toBGR( capture );
+#ifndef NDEBUG
+                               printf( "(DEBUG)icvRetrieveFrameAVI_XINE: converted YUY2 to BGR.\n" );
+#endif
+                               break;
+                               case XINE_IMGFMT_XVMC: printf( "(ERROR)icvRetrieveFrameAVI_XINE: XVMC format not supported!\n" );
+                               break;
+
+                               case XINE_IMGFMT_XXMC: printf( "(ERROR)icvRetrieveFrameAVI_XINE: XXMC format not supported!\n" );
+                               break;
+
+                               default: printf( "(ERROR)icvRetrieveFrameAVI_XINE: unknown color/pixel format!\n" );
+               }
+
+               /* always release last xine_frame, not needed anymore, but store its frame_number in *capture ! */
+               xine_free_video_frame( capture->vo_port, &capture->xine_frame );
+               capture->xine_frame.data = 0;
+
+#ifndef NDEBUG
+               fprintf( stderr, "(DEBUG) icvRetrieveFrameAVI_XINE ... end\n" );
+#endif
+               return capture->bgr_frame;
+       }
+
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvRetrieveFrameAVI_XINE ... failed!\n" );
+#endif
+       return 0;
+}
+
+
+/**
+ * THIS FUNCTION IS A FALLBACK FUNCTION FOR THE CASE THAT THE XINE SEEK IMPLEMENTATION
+ * DOESN'T WORK WITH THE ACTUAL INPUT. THIS FUNCTION IS ONLY USED IN THE CASE OF AN EMERGENCY,
+ * BECAUSE IT IS VERY SLOW !
+**/
+static int icvOldSeekFrameAVI_XINE( CvCaptureAVI_XINE* capture, int f )
+{
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvOldSeekFrameAVI_XINE ... start\n" );
+#endif
+
+       OPENCV_ASSERT ( capture,
+                        "icvRetricvOldSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture");
+       OPENCV_ASSERT ( capture->stream,
+                        "icvOldSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
+       OPENCV_ASSERT ( capture->vo_port,
+                        "icvOldSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->vo_port");
+
+// not needed tnx to asserts...
+       // we need a valid capture context and it's stream to seek through
+//     if ( !capture || !capture->stream ) return 0;
+
+       // no need to seek if we are already there...
+       if ( f == capture->frame_number )
+       {
+#ifndef NDEBUG
+               fprintf( stderr, "(DEBUG) icvOldSeekFrameAVI_XINE ... end\n" );
+#endif
+               return 1;
+       }
+       // if the requested position is behind out actual position,
+       // we just need to read the remaining amount of frames until we are there.
+       else if ( f > capture->frame_number )
+       {
+               for ( ;capture->frame_number < f;capture->frame_number++ )
+                       /// un-increment framenumber grabbing failed
+                       if ( !xine_get_next_video_frame( capture->vo_port, &capture->xine_frame ) )
+                       {
+                               capture->frame_number--;
+                               break;
+                       }
+                       else
+                       {
+                               xine_free_video_frame( capture->vo_port, &capture->xine_frame );
+                       }
+       }
+       // otherwise we need to reset the stream and
+       // start reading frames from the beginning.
+       else // f < capture->frame_number
+       {
+               /// reset stream, should also work with non-seekable input
+               xine_play( capture->stream, 0, 0 );
+               /// read frames until we are at the requested frame
+               for ( capture->frame_number = 0; capture->frame_number < f; capture->frame_number++ )
+                       /// un-increment last framenumber if grabbing failed
+                       if ( !xine_get_next_video_frame( capture->vo_port, &capture->xine_frame ) )
+                       {
+                               capture->frame_number--;
+                               break;
+                       }
+                       else
+                       {
+                               xine_free_video_frame( capture->vo_port, &capture->xine_frame );
+                       }
+       }
+
+
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvOldSeekFrameAVI_XINE ... end\n" );
+#endif
+       return ( f == capture->frame_number ) ? 1 : 0;
+}
+
+
+static int icvSeekFrameAVI_XINE( CvCaptureAVI_XINE* capture, int f )
+{
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... start\n" );
+#endif
+
+       OPENCV_ASSERT ( capture,
+                        "icvSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture");
+       OPENCV_ASSERT ( capture->stream,
+                        "icvSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
+       OPENCV_ASSERT ( capture->vo_port,
+                        "icvSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->vo_port");
+
+// not needed tnx to asserts...
+       // we need a valid capture context and it's stream to seek through
+//     if ( !capture || !capture->stream ) return 0;
+
+       if ( capture->seekable )
+       {
+
+               /// use xinelib's seek functionality
+               int new_time = ( int ) ( ( f + 1 ) * ( float ) capture->frame_duration );
+
+#ifndef NDEBUG
+               fprintf( stderr, "(DEBUG) calling xine_play()" );
+#endif
+               if ( xine_play( capture->stream, 0, new_time ) )
+               {
+#ifndef NDEBUG
+                       fprintf( stderr, "ok\n" );
+                       fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... end\n" );
+#endif
+                       capture->frame_number = f;
+                       return 1;
+               }
+               else
+               {
+#ifndef NDEBUG
+                       fprintf( stderr, "failed\n" );
+                       fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... failed\n" );
+#endif
+                       return 0;
+               }
+       }
+       else
+       {
+#ifndef NDEBUG
+               fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... end\n" );
+#endif
+               return icvOldSeekFrameAVI_XINE( capture, f );
+       }
+}
+
+
+static int icvSeekTimeAVI_XINE( CvCaptureAVI_XINE* capture, int t )
+{
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvSeekTimeAVI_XINE ... start\n" );
+#endif
+
+       OPENCV_ASSERT ( capture,
+                        "icvSeekTimeAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture");
+       OPENCV_ASSERT ( capture->stream,
+                        "icvSeekTimeAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
+       OPENCV_ASSERT ( capture->vo_port,
+                        "icvSeekTimeAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->vo_port");
+
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvSeekTimeAVI_XINE ... start\n" );
+#endif
+
+// not needed tnx to asserts...
+       // we need a valid capture context and it's stream to seek through
+//     if ( !capture || !capture->stream ) return 0;
+
+       if ( capture->seekable )
+       {
+               /// use xinelib's seek functionality
+               if ( xine_play( capture->stream, 0, t ) )
+               {
+                       capture->frame_number = ( int ) ( ( float ) t * capture->frame_rate / 1000 );
+#ifndef NDEBUG
+                       fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... end\n" );
+#endif
+                       return 1;
+               }
+               else
+               {
+#ifndef NDEBUG
+                       fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... failed!\n" );
+#endif
+                       return 0;
+               }
+       }
+       else
+       {
+               int new_frame = ( int ) ( ( float ) t * capture->frame_rate / 1000 );
+#ifndef NDEBUG
+               fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ....end\n" );
+#endif
+               return icvOldSeekFrameAVI_XINE( capture, new_frame );
+       }
+}
+
+
+static int icvSeekRatioAVI_XINE( CvCaptureAVI_XINE* capture, double ratio )
+{
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... start\n" );
+#endif
+
+       OPENCV_ASSERT ( capture,
+                        "icvSeekRatioAVI_XINE( CvCaptureAVI_XINE *, double )", "illegal capture");
+       OPENCV_ASSERT ( capture->stream,
+                        "icvSeekRatioAVI_XINE( CvCaptureAVI_XINE *, double )", "illegal capture->stream");
+       OPENCV_ASSERT ( capture->vo_port,
+                        "icvSeekRatioAVI_XINE( CvCaptureAVI_XINE *, double )", "illegal capture->vo_port");
+
+// not needed tnx to asserts...
+       // we need a valid capture context and it's stream to seek through
+//     if ( !capture || !capture->stream ) return 0;
+
+       /// ratio must be [0..1]
+       if ( ratio > 1 || ratio < 0 ) return 0;
+
+       if ( capture->seekable )
+       {
+       // TODO: FIX IT, DOESN'T WORK PROPERLY, YET...!
+               int pos_t, pos_l, length;
+               xine_get_pos_length( capture->stream, &pos_l, &pos_t, &length );
+               fprintf( stderr, "ratio on GetProperty(): %d\n", pos_l );
+
+               /// use xinelib's seek functionality
+               if ( xine_play( capture->stream, (int)(ratio*(float)length), 0 ) )
+               {
+                       capture->frame_number = ( int ) ( ratio*length / capture->frame_duration );
+               }
+               else
+               {
+#ifndef NDEBUG
+                       fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... failed!\n" );
+#endif
+                       return 0;
+               }
+       }
+       else
+       {
+               /// TODO: fill it !
+               fprintf( stderr, "icvSeekRatioAVI_XINE(): Seek not supported by stream !\n" );
+               fprintf( stderr, "icvSeekRatioAVI_XINE(): (seek in stream with NO seek support NOT implemented...yet!)\n" );
+#ifndef NDEBUG
+               fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... failed!\n" );
+#endif
+               return 0;
+       }
+
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... end!\n" );
+#endif
+       return 1;
+}
+
+
+static double icvGetPropertyAVI_XINE( CvCaptureAVI_XINE* capture, int property_id )
+{
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvGetPropertyAVI_XINE ... start\n" );
+#endif
+
+       OPENCV_ASSERT ( capture,
+                        "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture");
+       OPENCV_ASSERT ( capture->stream,
+                        "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
+       OPENCV_ASSERT ( capture->vo_port,
+                        "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->vo_port");
+       OPENCV_ASSERT ( capture->xine,
+                        "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->xine");
+       OPENCV_ASSERT ( capture->bgr_frame,
+                        "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->bgr_frame");
+
+// not needed tnx to asserts...
+       // we need a valid capture context and it's stream to seek through
+//     if ( !capture || !capture->stream || !capture->bgr_frame || !capture->xine || !capture->vo_port ) return 0
+
+       int pos_t, pos_l, length;
+       xine_get_pos_length( capture->stream, &pos_l, &pos_t, &length );
+       fprintf( stderr, "ratio on GetProperty(): %i\n", pos_l );
+
+       switch ( property_id )
+       {
+                       /// return actual position in msec
+                       case CV_CAP_PROP_POS_MSEC:
+                       if ( !capture->seekable )
+                       {
+                               fprintf( stderr, "(ERROR) GetPropertyAVI_XINE(CV_CAP_PROP_POS_MSEC:\n" );
+                               fprintf( stderr, "      Stream is NOT seekable, so position info may NOT be valid !!\n" );
+                       }
+                       return pos_t;
+
+                       /// return actual frame number
+                       case CV_CAP_PROP_POS_FRAMES:
+                       /// we insist the capture->frame_number to be remain updated !!!!
+                       return capture->frame_number;
+
+                       /// return actual position ratio in the range [0..1] depending on
+                       /// the total length of the stream and the actual position
+                       case CV_CAP_PROP_POS_AVI_RATIO:
+                       if ( !capture->seekable )
+                       {
+                               fprintf( stderr, "(ERROR) GetPropertyAVI_XINE(CV_CAP_PROP_POS_AVI_RATIO:\n" );
+                               fprintf( stderr, "      Stream is NOT seekable, so ratio info may NOT be valid !!\n" );
+                       }
+                       if ( length == 0 ) break;
+                       else return pos_l / 65535;
+
+
+                       /// return width of image source
+                       case CV_CAP_PROP_FRAME_WIDTH:
+                       return capture->size.width;
+
+                       /// return height of image source
+                       case CV_CAP_PROP_FRAME_HEIGHT:
+                       return capture->size.height;
+
+                       /// return framerate of stream
+                       case CV_CAP_PROP_FPS:
+                       if ( !capture->seekable )
+                       {
+                               fprintf( stderr, "(ERROR) GetPropertyAVI_XINE(CV_CAP_PROP_FPS:\n" );
+                               fprintf( stderr, "      Stream is NOT seekable, so FPS info may NOT be valid !!\n" );
+                       }
+                       return capture->frame_rate;
+
+                       /// return four-character-code (FOURCC) of source's codec
+                       case CV_CAP_PROP_FOURCC:
+                       return ( double ) xine_get_stream_info( capture->stream, XINE_STREAM_INFO_VIDEO_FOURCC );
+       }
+
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvGetPropertyAVI_XINE ... failed!\n" );
+#endif
+
+       return 0;
+}
+
+
+static int icvSetPropertyAVI_XINE( CvCaptureAVI_XINE* capture,
+                                   int property_id, double value )
+{
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvSetPropertyAVI_XINE ... start\n" );
+#endif
+
+       OPENCV_ASSERT ( capture,
+                        "icvSetPropertyAVI_XINE( CvCaptureAVI_XINE *, int, double )", "illegal capture");
+       OPENCV_ASSERT ( capture->stream,
+                        "icvGetPropericvSetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
+       OPENCV_ASSERT ( capture->vo_port,
+                        "icvSetPropertyAVI_XINE( CvCaptureAVI_XINE *, int, double )", "illegal capture->vo_port");
+
+// not needed tnx to asserts...
+       // we need a valid capture context and it's stream to seek through
+//     if ( !capture || !capture->stream || !capture->bgr_frame || !capture->xine || !capture->vo_port ) return 0
+
+#ifndef NDEBUG
+       fprintf( stderr, "(DEBUG) icvSetPropertyAVI_XINE: seeking to value %f ... ", value );
+#endif
+
+       switch ( property_id )
+       {
+                       /// set (seek to) position in msec
+                       case CV_CAP_PROP_POS_MSEC:
+                       return icvSeekTimeAVI_XINE( capture, ( int ) value );
+
+                       /// set (seek to) frame number
+                       case CV_CAP_PROP_POS_FRAMES:
+                       return icvSeekFrameAVI_XINE( capture, ( int ) value );
+
+                       /// set (seek to) position ratio in the range [0..1] depending on
+                       /// the total length of the stream and the actual position
+                       case CV_CAP_PROP_POS_AVI_RATIO:
+                       return icvSeekRatioAVI_XINE( capture, value );
+
+                       default:
+#ifndef NDEBUG
+                       fprintf( stderr, "(DEBUG) icvSetPropertyAVI_XINE ... failed!\n" );
+#endif
+
+                       return 0;
+       }
+}
+
+
+static CvCaptureAVI_XINE* icvCaptureFromFile_XINE( const char* filename )
+{
+       // construct capture struct
+       CvCaptureAVI_XINE * capture = ( CvCaptureAVI_XINE* ) cvAlloc ( sizeof ( CvCaptureAVI_XINE ) );
+       memset( capture, 0, sizeof ( CvCaptureAVI_XINE ) );
+
+       // initialize XINE
+       if ( !icvOpenAVI_XINE( capture, filename ) )
+               return 0;
+
+       OPENCV_ASSERT ( capture,
+                        "cvCaptureFromFile_XINE( const char * )", "couldn't create capture");
+
+       return capture;
+
+}
+
+
+
+class CvCaptureAVI_XINE_CPP : public CvCapture
+{
+public:
+    CvCaptureAVI_XINE_CPP() { captureXINE = 0; }
+    virtual ~CvCaptureAVI_XINE_CPP() { close(); }
+
+    virtual bool open( const char* filename );
+    virtual void close();
+
+    virtual double getProperty(int);
+    virtual bool setProperty(int, double);
+    virtual bool grabFrame();
+    virtual IplImage* retrieveFrame(int);
+protected:
+
+    CvCaptureAVI_XINE* captureXINE;
+};
+
+bool CvCaptureAVI_XINE_CPP::open( const char* filename )
+{
+    close();
+    captureXINE = icvCaptureFromFile_XINE(filename);
+    return captureXINE != 0;
+}
+
+void CvCaptureAVI_XINE_CPP::close()
+{
+    if( captureXINE )
+    {
+        icvCloseAVI_XINE( captureXINE );
+        cvFree( &captureXINE );
+    }
+}
+
+bool CvCaptureAVI_XINE_CPP::grabFrame()
+{
+    return captureXINE ? icvGrabFrameAVI_XINE( captureXINE ) != 0 : false;
+}
+
+IplImage* CvCaptureAVI_XINE_CPP::retrieveFrame(int)
+{
+    return captureXINE ? (IplImage*)icvRetrieveFrameAVI_XINE( captureXINE, 0 ) : 0;
+}
+
+double CvCaptureAVI_XINE_CPP::getProperty( int propId )
+{
+    return captureXINE ? icvGetPropertyAVI_XINE( captureXINE, propId ) : 0;
+}
+
+bool CvCaptureAVI_XINE_CPP::setProperty( int propId, double value )
+{
+    return captureXINE ? icvSetPropertyAVI_XINE( captureXINE, propId, value ) != 0 : false;
+}
+
+CvCapture* cvCreateFileCapture_XINE(const char* filename)
+{
+    CvCaptureAVI_XINE_CPP* capture = new CvCaptureAVI_XINE_CPP;
+
+    if( capture->open(filename))
+        return capture;
+
+    delete capture;
+    return 0;
+}
+
+
+#undef NDEBUG