@ -1,4 +1,4 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
/*M//////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
@ -45,802 +45,311 @@
// Institute of Communications Engineering
// RWTH Aachen University
# include "precomp.hpp"
// required to enable some functions used here...
# define XINE_ENABLE_EXPERIMENTAL_FEATURES
# include <cassert>
extern " C "
{
# include <xine.h>
//#include <xine/xineutils.h>
# include <xine/xineutils.h>
// forward declaration from <xine/xineutils.h>
const char * xine_get_homedir ( void ) ;
}
using namespace cv ;
typedef struct CvCaptureAVI_XINE
class XINECapture : public IVideoCapture
{
/// method call table
// 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 !!!!
Size size ;
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
double frame_rate ; // fps
double frame_duration ; // ms
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
public :
XINECapture ( )
: xine ( 0 ) , stream ( 0 ) , vo_port ( 0 ) , frame_number ( - 1 ) , frame_rate ( 0. ) , frame_duration ( 0. ) ,
seekable ( false )
{
capture - > yuv_frame - > imageData [ offset ] = v [ 0 ] ;
xine_video_frame_t z = { } ;
xine_frame = z ;
}
}
}
// 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 ;
~ XINECapture ( ) { close ( ) ; }
int size_Y = w_Y * h_Y ;
int size_UV = size_Y / 4 ;
bool isOpened ( ) const CV_OVERRIDE { return xine & & stream ; }
int line = yuv - > widthStep ;
int getCaptureDomain ( ) CV_OVERRIDE { return CAP_XINE ; }
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 )
void close ( )
{
/*
if ( x & 1 )
if ( vo_port & & xine_frame . data )
{
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 ;
xine_free_video_frame ( vo_port , & xine_frame ) ;
}
if ( y & 1 )
if ( stream )
{
addr_U - = w_UV ;
addr_V - = w_UV ;
}
}
/* convert to BGR */
cvCvtColor ( capture - > yuv_frame , capture - > bgr_frame , CV_YCrCb2BGR ) ;
xine_close ( stream ) ;
stream = 0 ;
}
static void icvCloseAVI_XINE ( CvCaptureAVI_XINE * capture )
if ( vo_port )
{
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 ) ;
xine_close_video_driver ( xine , vo_port ) ;
vo_port = 0 ;
}
/**
* CHECKS IF THE STREAM IN * capture IS SEEKABLE .
* */
static void icvCheckSeekAVI_XINE ( CvCaptureAVI_XINE * capture )
if ( xine )
{
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
xine_exit ( xine ) ;
xine = 0 ;
}
}
static int icvOpenAVI_XINE ( CvCaptureAVI_XINE * capture , const char * filename )
bool open ( const char * filename )
{
# ifndef NDEBUG
fprintf ( stderr , " (DEBUG) icvOpenAVI_XINE ... start \n " ) ;
# endif
CV_Assert ( ! xine , ! stream , ! vo_port ) ;
char configfile [ 2048 ] = { 0 } ;
char configfile [ 2048 ] ;
capture - > xine = xine_new ( ) ;
xine = xine_new ( ) ;
sprintf ( configfile , " %s%s " , xine_get_homedir ( ) , " /.xine/config " ) ;
xine_config_load ( xine , configfile ) ;
xine_init ( xine ) ;
xine_engine_set_param ( xine , 0 , 0 ) ;
xine_config_load ( capture - > xine , configfile ) ;
xine_init ( capture - > xine ) ;
vo_port = xine_new_framegrab_video_port ( xine ) ;
if ( ! vo_port )
return false ;
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 ;
}
stream = xine_stream_new ( xine , NULL , vo_port ) ;
if ( ! xine_open ( stream , filename ) )
return false ;
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 ) ;
if ( ! xine_play ( stream , 0 , 0 ) )
return false ;
// 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 ;
frame_number = 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 ;
if ( ! xine_get_next_video_frame ( vo_port , & xine_frame ) )
return false ;
# ifndef NDEBUG
fprintf ( stderr , " (DEBUG) frame_duration = %f, framerate = %f \n " , capture - > frame_duration , capture - > frame_rate ) ;
# endif
size = Size ( xine_frame . width , xine_frame . height ) ;
OPENCV_ASSERT ( capture - > yuv_frame ,
" icvOpenAVI_XINE( CvCaptureAVI_XINE *, const char *) " , " couldn't create yuv frame " ) ;
xine_free_video_frame ( vo_port , & xine_frame ) ;
xine_frame . data = 0 ;
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 ;
{
xine_video_frame_t tmp ;
if ( ! xine_play ( stream , 0 , 300 ) ) /* 300msec */
return false ;
if ( ! xine_get_next_video_frame ( vo_port , & tmp ) )
return false ;
seekable = ( tmp . frame_number ! = 0 ) ;
xine_free_video_frame ( vo_port , & tmp ) ;
if ( ! xine_play ( stream , 0 , 0 ) )
return false ;
}
frame_duration = xine_get_stream_info ( stream , XINE_STREAM_INFO_FRAME_DURATION ) / 90. ;
frame_rate = frame_duration > 0 ? 1000 / frame_duration : 0. ;
return true ;
}
static int icvGrabFrameAVI_XINE ( CvCaptureAVI_XINE * capture )
bool grabFrame ( ) CV_OVERRIDE
{
# 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
CV_Assert ( vo_port ) ;
bool res = xine_get_next_video_frame ( vo_port , & xine_frame ) ;
if ( res )
frame_number + + ;
return res ;
}
static const IplImage * icvRetrieveFrameAVI_XINE ( CvCaptureAVI_XINE * capture , int )
bool retrieveFrame ( int , OutputArray out ) CV_OVERRIDE
{
# ifndef NDEBUG
fprintf ( stderr , " (DEBUG) icvRetrieveFrameAVI_XINE ... start \n " ) ;
# endif
CV_Assert ( stream ) ;
CV_Assert ( vo_port ) ;
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 " ) ;
if ( xine_frame . data = = 0 )
return false ;
/* 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 ;
}
bool res = false ;
Mat frame_bgr ;
if ( res )
switch ( xine_frame . colorspace )
{
switch ( capture - > xine_frame . colorspace )
case XINE_IMGFMT_YV12 : // actual format seems to be I420 (or IYUV)
{
case XINE_IMGFMT_YV12 : icvYV12toBGR ( capture ) ;
# ifndef NDEBUG
printf ( " (DEBUG)icvRetrieveFrameAVI_XINE: converted YV12 to BGR. \n " ) ;
# endif
Mat frame ( Size ( xine_frame . width , xine_frame . height * 3 / 2 ) , CV_8UC1 , xine_frame . data ) ;
cv : : cvtColor ( frame , out , cv : : COLOR_YUV2BGR_I420 ) ;
res = true ;
}
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 " ) ;
case XINE_IMGFMT_YUY2 :
{
Mat frame ( Size ( xine_frame . width , xine_frame . height ) , CV_8UC2 , xine_frame . data ) ;
cv : : cvtColor ( frame , out , cv : : COLOR_YUV2BGR_YUY2 ) ;
res = true ;
}
break ;
case XINE_IMGFMT_XXMC : printf ( " (ERROR)icvRetrieveFrameAVI_XINE: XXMC format not supported! \n " ) ;
default :
break ;
}
default : printf ( " (ERROR)icvRetrieveFrameAVI_XINE: unknown color/pixel format! \n " ) ;
// always release last xine_frame, not needed anymore
xine_free_video_frame ( vo_port , & xine_frame ) ;
xine_frame . data = 0 ;
return res ;
}
/* 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 ;
double getProperty ( int property_id ) const CV_OVERRIDE
{
CV_Assert ( xine , vo_port , stream ) ;
int pos_t , pos_l , length ;
bool res = ( bool ) xine_get_pos_length ( stream , & pos_l , & pos_t , & length ) ;
# ifndef NDEBUG
fprintf ( stderr , " (DEBUG) icvRetrieveFrameAVI_XINE ... end \n " ) ;
# endif
return capture - > bgr_frame ;
switch ( property_id )
{
case CV_CAP_PROP_POS_MSEC : return res ? pos_t : 0 ;
case CV_CAP_PROP_POS_FRAMES : return frame_number ;
case CV_CAP_PROP_POS_AVI_RATIO : return length & & res ? pos_l / 65535.0 : 0.0 ;
case CV_CAP_PROP_FRAME_WIDTH : return size . width ;
case CV_CAP_PROP_FRAME_HEIGHT : return size . height ;
case CV_CAP_PROP_FPS : return frame_rate ;
case CV_CAP_PROP_FOURCC : return ( double ) xine_get_stream_info ( stream , XINE_STREAM_INFO_VIDEO_FOURCC ) ;
}
# 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 )
bool setProperty ( int property_id , double value ) CV_OVERRIDE
{
# 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;
CV_Assert ( stream ) ;
CV_Assert ( vo_port ) ;
switch ( property_id )
{
case CV_CAP_PROP_POS_MSEC : return seekTime ( ( int ) value ) ;
case CV_CAP_PROP_POS_FRAMES : return seekFrame ( ( int ) value ) ;
case CV_CAP_PROP_POS_AVI_RATIO : return seekRatio ( value ) ;
default : return false ;
}
}
protected :
bool oldSeekFrame ( int f )
{
CV_Assert ( xine , vo_port , stream ) ;
// no need to seek if we are already there...
if ( f = = capture - > frame_number )
if ( f = = frame_number )
{
# ifndef NDEBUG
fprintf ( stderr , " (DEBUG) icvOldSeekFrameAVI_XINE ... end \n " ) ;
# endif
return 1 ;
return true ;
}
else if ( f > frame_number )
{
// 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 ( ; frame_number < f ; 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 ) )
// un-increment framenumber grabbing failed
if ( ! xine_get_next_video_frame ( vo_port , & xine_frame ) )
{
capture - > frame_number - - ;
frame_number - - ;
break ;
}
else
{
xine_free_video_frame ( capture - > vo_port , & capture - > xine_frame ) ;
xine_free_video_frame ( vo_port , & xine_frame ) ;
}
}
}
else // f < frame_number
{
// 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 ( stream , 0 , 0 ) ;
// read frames until we are at the requested frame
for ( frame_number = 0 ; frame_number < f ; 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 ) )
// un-increment last framenumber if grabbing failed
if ( ! xine_get_next_video_frame ( vo_port , & xine_frame ) )
{
capture - > frame_number - - ;
frame_number - - ;
break ;
}
else
{
xine_free_video_frame ( capture - > vo_port , & capture - > xine_frame ) ;
xine_free_video_frame ( vo_port , & xine_frame ) ;
}
}
# ifndef NDEBUG
fprintf ( stderr , " (DEBUG) icvOldSeekFrameAVI_XINE ... end \n " ) ;
# endif
return ( f = = capture - > frame_number ) ? 1 : 0 ;
}
return f = = frame_number ;
}
static int icvSeekFrameAVI_XINE ( CvCaptureAVI_XINE * capture , int f )
bool seekFrame ( 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 )
CV_Assert ( xine , vo_port , stream ) ;
if ( 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 ) )
int new_time = ( int ) ( ( f + 1 ) * ( float ) frame_duration ) ;
if ( xine_play ( 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 ;
frame_number = f ;
return true ;
}
}
else
{
# ifndef NDEBUG
fprintf ( stderr , " (DEBUG) icvSeekFrameAVI_XINE ... end \n " ) ;
# endif
return icvOldSeekFrameAVI_XINE ( capture , f ) ;
return oldSeekFrame ( f ) ;
}
return false ;
}
static int icvSeekTimeAVI_XINE ( CvCaptureAVI_XINE * capture , int t )
bool seekTime ( 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 )
CV_Assert ( xine , vo_port , stream ) ;
if ( seekable )
{
/// use xinelib's seek functionality
if ( xine_play ( capture - > stream , 0 , t ) )
if ( xine_play ( 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 ;
frame_number = ( int ) ( ( double ) t * frame_rate / 1000 ) ;
return true ;
}
}
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 ) ;
int new_frame = ( int ) ( ( double ) t * frame_rate / 1000 ) ;
return oldSeekFrame ( new_frame ) ;
}
return false ;
}
static int icvSeekRatioAVI_XINE ( CvCaptureAVI_XINE * capture , double ratio )
bool seekRatio ( 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 )
CV_Assert ( xine , vo_port , stream ) ;
if ( ratio > 1 | | ratio < 0 )
return false ;
if ( 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 )
bool res = ( bool ) xine_get_pos_length ( stream , & pos_l , & pos_t , & length ) ;
if ( res & & xine_play ( stream , ( int ) ( ratio * ( double ) length ) , 0 ) )
{
# 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 ;
frame_number = ( int ) ( ratio * length / frame_duration ) ;
return true ;
}
}
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 ;
return false ;
}
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 ) const CV_OVERRIDE ;
virtual bool setProperty ( int , double ) CV_OVERRIDE ;
virtual bool grabFrame ( ) CV_OVERRIDE ;
virtual IplImage * retrieveFrame ( int ) CV_OVERRIDE ;
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 ( )
Ptr < IVideoCapture > cv : : createXINECapture ( const char * filename )
{
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 ) const
{
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 ;
Ptr < XINECapture > res = makePtr < XINECapture > ( ) ;
if ( res & & res - > open ( filename ) )
return res ;
return Ptr < IVideoCapture > ( ) ;
}
# undef NDEBUG