mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
846 lines
27 KiB
846 lines
27 KiB
/*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 "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> |
|
|
|
// 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
|
|
|