• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41 
42 // Authors: Konstantin Dols <dols@ient.rwth-aachen.de>
43 //          Mark Asbach <asbach@ient.rwth-aachen.de>
44 //
45 //          Institute of Communications Engineering
46 //          RWTH Aachen University
47 
48 
49 #include "precomp.hpp"
50 
51 // required to enable some functions used here...
52 #define XINE_ENABLE_EXPERIMENTAL_FEATURES
53 
54 #include <cassert>
55 
56 extern "C"
57 {
58 #include <xine.h>
59     //#include <xine/xineutils.h>
60 
61     // forward declaration from <xine/xineutils.h>
62     const char *xine_get_homedir( void );
63 }
64 
65 typedef struct CvCaptureAVI_XINE
66 {
67     /// method call table
68     xine_t * xine;
69     xine_stream_t * stream;
70     xine_video_port_t * vo_port;
71 
72     /// frame returned by xine_get_next_video_frame()
73     xine_video_frame_t xine_frame;
74 
75     IplImage	* yuv_frame;
76     IplImage	* bgr_frame;
77 
78     /// image dimansions of the input stream.
79     CvSize	size;
80 
81     /// framenumber of the last frame received from xine_get_next_video_frame().
82     /// note: always keep this value updated !!!!
83     int	frame_number;
84 
85     /// framerate of the opened stream
86     double	frame_rate;
87 
88     /// duration of a frame in stream
89     double	frame_duration;
90 
91     /// indicated if input is seekable
92     bool	seekable;
93 
94 }
95 CvCaptureAVI_XINE;
96 
97 
98 // 4:2:2 interleaved -> BGR
icvYUY2toBGR(CvCaptureAVI_XINE * capture)99 static void icvYUY2toBGR( CvCaptureAVI_XINE * capture )
100 {
101     uint8_t * v	= capture->xine_frame.data;
102     int offset;
103     for ( int y = 0; y < capture->yuv_frame->height; y++ )
104     {
105         offset	= y * capture->yuv_frame->widthStep;
106 
107         for ( int x = 0; x < capture->yuv_frame->width; x++, offset += 3 )
108         {
109             capture->yuv_frame->imageData[ offset + 1 ] = v[ 3 ];
110             capture->yuv_frame->imageData[ offset + 2 ] = v[ 1 ];
111             if ( x & 1 )
112             {
113                 capture->yuv_frame->imageData[ offset ] = v[ 2 ];
114                 v += 4;
115             }
116             else
117             {
118                 capture->yuv_frame->imageData[ offset ] = v[ 0 ];
119             }
120         }
121     }
122 
123     // convert to BGR
124     cvCvtColor( capture->yuv_frame, capture->bgr_frame, CV_YCrCb2BGR );
125 }
126 
127 
128 // 4:2:0 planary -> BGR
icvYV12toBGR(CvCaptureAVI_XINE * capture)129 static void icvYV12toBGR( CvCaptureAVI_XINE * capture )
130 {
131     IplImage * yuv	= capture->yuv_frame;
132     int	w_Y	= capture->size.width;
133     int	h_Y	= capture->size.height;
134 
135     int	w_UV	= w_Y >> 1;
136 
137     int	size_Y	= w_Y * h_Y;
138     int	size_UV	= size_Y / 4;
139 
140     int	line	= yuv->widthStep;
141 
142     uint8_t * addr_Y = capture->xine_frame.data;
143     uint8_t * addr_U = addr_Y + size_Y;
144     uint8_t * addr_V = addr_U + size_UV;
145 
146     // YYYY..UU.VV. -> BGRBGRBGR...
147     for ( int y = 0; y < h_Y; y++ )
148     {
149         int offset = y * line;
150         for ( int x = 0; x < w_Y; x++, offset += 3 )
151         {
152             /*
153             if ( x&1 )
154             {
155                 addr_U++; addr_V++;
156             }
157             */
158             int one_zero = x & 1;
159             addr_U += one_zero;
160             addr_V += one_zero;
161 
162             yuv->imageData[ offset ] = *( addr_Y++ );
163             yuv->imageData[ offset + 1 ] = *addr_U;
164             yuv->imageData[ offset + 2 ] = *addr_V;
165         }
166 
167         if ( y & 1 )
168         {
169             addr_U -= w_UV;
170             addr_V -= w_UV;
171         }
172     }
173 
174     /* convert to BGR */
175     cvCvtColor( capture->yuv_frame, capture->bgr_frame, CV_YCrCb2BGR );
176 }
177 
icvCloseAVI_XINE(CvCaptureAVI_XINE * capture)178 static void icvCloseAVI_XINE( CvCaptureAVI_XINE* capture )
179 {
180     xine_free_video_frame( capture->vo_port, &capture->xine_frame );
181 
182     if ( capture->yuv_frame ) cvReleaseImage( &capture->yuv_frame );
183     if ( capture->bgr_frame ) cvReleaseImage( &capture->bgr_frame );
184 
185     xine_close( capture->stream );
186     //	xine_dispose( capture->stream );
187 
188     if ( capture->vo_port ) xine_close_video_driver( capture->xine, capture->vo_port );
189 
190     xine_exit( capture->xine );
191 }
192 
193 
194 /**
195  * CHECKS IF THE STREAM IN * capture IS SEEKABLE.
196 **/
icvCheckSeekAVI_XINE(CvCaptureAVI_XINE * capture)197 static void icvCheckSeekAVI_XINE( CvCaptureAVI_XINE * capture )
198 {
199     OPENCV_ASSERT ( capture,                        "icvCheckSeekAVI_XINE( CvCaptureAVI_XINE* )", "illegal capture");
200     OPENCV_ASSERT ( capture->stream,
201                         "icvCheckSeekAVI_XINE( CvCaptureAVI_XINE* )", "illegal capture->stream");
202     OPENCV_ASSERT ( capture->vo_port,
203                         "icvCheckSeekAVI_XINE( CvCaptureAVI_XINE* )", "illegal capture->vo_port");
204 
205 #ifndef NDEBUG
206     fprintf( stderr, "(DEBUG) icvCheckSeekAVI_XINE ... start\n" );
207 #endif
208 
209     // temp. frame for testing.
210     xine_video_frame_t tmp;
211     // try to seek to a future frame...
212     xine_play( capture->stream, 0, 300 ); /* 300msec */
213     // try to receive the frame...
214     xine_get_next_video_frame( capture->vo_port, &tmp );
215     // if the framenumber is still 0, we can't use the xine seek functionality
216     capture->seekable = ( tmp.frame_number != 0 );
217     // reset stream
218     xine_play( capture->stream, 0, 0 );
219     // release xine_frame
220     xine_free_video_frame( capture->vo_port, &tmp );
221 
222 #ifndef NDEBUG
223     if ( capture->seekable )
224         fprintf( stderr, "(DEBUG) icvCheckSeekAVI_XINE: Input is seekable, using XINE seek implementation.\n" );
225     else
226         fprintf( stderr, "(DEBUG) icvCheckSeekAVI_XINE: Input is NOT seekable, using fallback function.\n" );
227 
228     fprintf( stderr, "(DEBUG) icvCheckSeekAVI_XINE ... end\n" );
229 #endif
230 }
231 
232 
icvOpenAVI_XINE(CvCaptureAVI_XINE * capture,const char * filename)233 static int icvOpenAVI_XINE( CvCaptureAVI_XINE* capture, const char* filename )
234 {
235 #ifndef NDEBUG
236     fprintf( stderr, "(DEBUG) icvOpenAVI_XINE ... start\n" );
237 #endif
238 
239     char configfile[ 2048 ];
240 
241     capture->xine = xine_new();
242     sprintf( configfile, "%s%s", xine_get_homedir(), "/.xine/config" );
243 
244     xine_config_load( capture->xine, configfile );
245     xine_init( capture->xine );
246 
247     xine_engine_set_param( capture->xine, 0, 0 );
248     capture->vo_port = xine_new_framegrab_video_port( capture->xine );
249     if ( capture->vo_port == NULL )
250     {
251         printf( "(ERROR)icvOpenAVI_XINE(): Unable to initialize video driver.\n" );
252         return 0;
253     }
254 
255     capture->stream = xine_stream_new( capture->xine, NULL, capture->vo_port );
256 
257     if ( !xine_open( capture->stream, filename ) )
258     {
259         printf( "(ERROR)icvOpenAVI_XINE(): Unable to open source '%s'\n", filename );
260         return 0;
261     }
262     // reset stream...
263     xine_play( capture->stream, 0, 0 );
264 
265 
266     // initialize some internals...
267     capture->frame_number = 0;
268 
269     if ( !xine_get_next_video_frame( capture->vo_port, &capture->xine_frame ) )
270     {
271 #ifndef NDEBUG
272         fprintf( stderr, "(DEBUG) icvOpenAVI_XINE ... failed!\n" );
273 #endif
274         return 0;
275     }
276 
277     capture->size = cvSize( capture->xine_frame.width, capture->xine_frame.height );
278     capture->yuv_frame = cvCreateImage( capture->size, IPL_DEPTH_8U, 3 );
279     capture->bgr_frame = cvCreateImage( capture->size, IPL_DEPTH_8U, 3 );
280 
281     xine_free_video_frame( capture->vo_port, &capture->xine_frame );
282     capture->xine_frame.data[ 0 ] = 0;
283 
284     icvCheckSeekAVI_XINE( capture );
285 
286     capture->frame_duration = xine_get_stream_info( capture->stream, XINE_STREAM_INFO_FRAME_DURATION ) / 90.;
287     capture->frame_rate = 1000 / capture->frame_duration;
288 
289 #ifndef NDEBUG
290     fprintf( stderr, "(DEBUG) frame_duration = %f, framerate = %f\n", capture->frame_duration, capture->frame_rate );
291 #endif
292 
293     OPENCV_ASSERT ( capture->yuv_frame,
294                         "icvOpenAVI_XINE( CvCaptureAVI_XINE *, const char *)", "couldn't create yuv frame");
295 
296     OPENCV_ASSERT ( capture->bgr_frame,
297                         "icvOpenAVI_XINE( CvCaptureAVI_XINE *, const char *)", "couldn't create bgr frame");
298 
299 #ifndef NDEBUG
300     fprintf( stderr, "(DEBUG) icvOpenAVI_XINE ... end\n" );
301 #endif
302     return 1;
303 }
304 
305 
icvGrabFrameAVI_XINE(CvCaptureAVI_XINE * capture)306 static int icvGrabFrameAVI_XINE( CvCaptureAVI_XINE* capture )
307 {
308 #ifndef NDEBUG
309     fprintf( stderr, "(DEBUG) icvGrabFrameAVI_XINE ... start\n" );
310 #endif
311 
312     OPENCV_ASSERT ( capture,
313                         "icvGrabFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture");
314     OPENCV_ASSERT ( capture->vo_port,
315                         "icvGrabFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture->vo_port");
316 
317     int res = xine_get_next_video_frame( capture->vo_port, &capture->xine_frame );
318 
319     /* always keep internal framenumber updated !!! */
320     if ( res ) capture->frame_number++;
321 
322 #ifndef NDEBUG
323     fprintf( stderr, "(DEBUG) icvGrabFrameAVI_XINE ... end\n" );
324 #endif
325     return res;
326 }
327 
328 
icvRetrieveFrameAVI_XINE(CvCaptureAVI_XINE * capture,int)329 static const IplImage* icvRetrieveFrameAVI_XINE( CvCaptureAVI_XINE* capture, int )
330 {
331 #ifndef NDEBUG
332     fprintf( stderr, "(DEBUG) icvRetrieveFrameAVI_XINE ... start\n" );
333 #endif
334 
335     OPENCV_ASSERT ( capture,
336                         "icvRetrieveFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture");
337     OPENCV_ASSERT ( capture->stream,
338                         "icvRetrieveFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture->stream");
339     OPENCV_ASSERT ( capture->vo_port,
340                         "icvRetrieveFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture->vo_port");
341 
342     /* no frame grabbed yet? so let's do it now! */
343     int res = 0;
344     if ( capture->xine_frame.data == 0 )
345     {
346         res = icvGrabFrameAVI_XINE( capture );
347     }
348     else
349     {
350         res = 1;
351     }
352 
353     if ( res )
354     {
355         switch ( capture->xine_frame.colorspace )
356         {
357                 case XINE_IMGFMT_YV12: icvYV12toBGR( capture );
358 #ifndef NDEBUG
359                 printf( "(DEBUG)icvRetrieveFrameAVI_XINE: converted YV12 to BGR.\n" );
360 #endif
361                 break;
362 
363                 case XINE_IMGFMT_YUY2: icvYUY2toBGR( capture );
364 #ifndef NDEBUG
365                 printf( "(DEBUG)icvRetrieveFrameAVI_XINE: converted YUY2 to BGR.\n" );
366 #endif
367                 break;
368                 case XINE_IMGFMT_XVMC: printf( "(ERROR)icvRetrieveFrameAVI_XINE: XVMC format not supported!\n" );
369                 break;
370 
371                 case XINE_IMGFMT_XXMC: printf( "(ERROR)icvRetrieveFrameAVI_XINE: XXMC format not supported!\n" );
372                 break;
373 
374                 default: printf( "(ERROR)icvRetrieveFrameAVI_XINE: unknown color/pixel format!\n" );
375         }
376 
377         /* always release last xine_frame, not needed anymore, but store its frame_number in *capture ! */
378         xine_free_video_frame( capture->vo_port, &capture->xine_frame );
379         capture->xine_frame.data = 0;
380 
381 #ifndef NDEBUG
382         fprintf( stderr, "(DEBUG) icvRetrieveFrameAVI_XINE ... end\n" );
383 #endif
384         return capture->bgr_frame;
385     }
386 
387 #ifndef NDEBUG
388     fprintf( stderr, "(DEBUG) icvRetrieveFrameAVI_XINE ... failed!\n" );
389 #endif
390     return 0;
391 }
392 
393 
394 /**
395  * THIS FUNCTION IS A FALLBACK FUNCTION FOR THE CASE THAT THE XINE SEEK IMPLEMENTATION
396  * DOESN'T WORK WITH THE ACTUAL INPUT. THIS FUNCTION IS ONLY USED IN THE CASE OF AN EMERGENCY,
397  * BECAUSE IT IS VERY SLOW !
398 **/
icvOldSeekFrameAVI_XINE(CvCaptureAVI_XINE * capture,int f)399 static int icvOldSeekFrameAVI_XINE( CvCaptureAVI_XINE* capture, int f )
400 {
401 #ifndef NDEBUG
402     fprintf( stderr, "(DEBUG) icvOldSeekFrameAVI_XINE ... start\n" );
403 #endif
404 
405     OPENCV_ASSERT ( capture,
406                         "icvRetricvOldSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture");
407     OPENCV_ASSERT ( capture->stream,
408                         "icvOldSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
409     OPENCV_ASSERT ( capture->vo_port,
410                         "icvOldSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->vo_port");
411 
412 // not needed tnx to asserts...
413     // we need a valid capture context and it's stream to seek through
414 //	if ( !capture || !capture->stream ) return 0;
415 
416     // no need to seek if we are already there...
417     if ( f == capture->frame_number )
418     {
419 #ifndef NDEBUG
420         fprintf( stderr, "(DEBUG) icvOldSeekFrameAVI_XINE ... end\n" );
421 #endif
422         return 1;
423     }
424     // if the requested position is behind out actual position,
425     // we just need to read the remaining amount of frames until we are there.
426     else if ( f > capture->frame_number )
427     {
428         for ( ;capture->frame_number < f;capture->frame_number++ )
429             /// un-increment framenumber grabbing failed
430             if ( !xine_get_next_video_frame( capture->vo_port, &capture->xine_frame ) )
431             {
432                 capture->frame_number--;
433                 break;
434             }
435             else
436             {
437                 xine_free_video_frame( capture->vo_port, &capture->xine_frame );
438             }
439     }
440     // otherwise we need to reset the stream and
441     // start reading frames from the beginning.
442     else // f < capture->frame_number
443     {
444         /// reset stream, should also work with non-seekable input
445         xine_play( capture->stream, 0, 0 );
446         /// read frames until we are at the requested frame
447         for ( capture->frame_number = 0; capture->frame_number < f; capture->frame_number++ )
448             /// un-increment last framenumber if grabbing failed
449             if ( !xine_get_next_video_frame( capture->vo_port, &capture->xine_frame ) )
450             {
451                 capture->frame_number--;
452                 break;
453             }
454             else
455             {
456                 xine_free_video_frame( capture->vo_port, &capture->xine_frame );
457             }
458     }
459 
460 
461 #ifndef NDEBUG
462     fprintf( stderr, "(DEBUG) icvOldSeekFrameAVI_XINE ... end\n" );
463 #endif
464     return ( f == capture->frame_number ) ? 1 : 0;
465 }
466 
467 
icvSeekFrameAVI_XINE(CvCaptureAVI_XINE * capture,int f)468 static int icvSeekFrameAVI_XINE( CvCaptureAVI_XINE* capture, int f )
469 {
470 #ifndef NDEBUG
471     fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... start\n" );
472 #endif
473 
474     OPENCV_ASSERT ( capture,
475                         "icvSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture");
476     OPENCV_ASSERT ( capture->stream,
477                         "icvSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
478     OPENCV_ASSERT ( capture->vo_port,
479                         "icvSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->vo_port");
480 
481 // not needed tnx to asserts...
482     // we need a valid capture context and it's stream to seek through
483 //	if ( !capture || !capture->stream ) return 0;
484 
485     if ( capture->seekable )
486     {
487 
488         /// use xinelib's seek functionality
489         int new_time = ( int ) ( ( f + 1 ) * ( float ) capture->frame_duration );
490 
491 #ifndef NDEBUG
492         fprintf( stderr, "(DEBUG) calling xine_play()" );
493 #endif
494         if ( xine_play( capture->stream, 0, new_time ) )
495         {
496 #ifndef NDEBUG
497             fprintf( stderr, "ok\n" );
498             fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... end\n" );
499 #endif
500             capture->frame_number = f;
501             return 1;
502         }
503         else
504         {
505 #ifndef NDEBUG
506             fprintf( stderr, "failed\n" );
507             fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... failed\n" );
508 #endif
509             return 0;
510         }
511     }
512     else
513     {
514 #ifndef NDEBUG
515         fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... end\n" );
516 #endif
517         return icvOldSeekFrameAVI_XINE( capture, f );
518     }
519 }
520 
521 
icvSeekTimeAVI_XINE(CvCaptureAVI_XINE * capture,int t)522 static int icvSeekTimeAVI_XINE( CvCaptureAVI_XINE* capture, int t )
523 {
524 #ifndef NDEBUG
525     fprintf( stderr, "(DEBUG) icvSeekTimeAVI_XINE ... start\n" );
526 #endif
527 
528     OPENCV_ASSERT ( capture,
529                         "icvSeekTimeAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture");
530     OPENCV_ASSERT ( capture->stream,
531                         "icvSeekTimeAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
532     OPENCV_ASSERT ( capture->vo_port,
533                         "icvSeekTimeAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->vo_port");
534 
535 #ifndef NDEBUG
536     fprintf( stderr, "(DEBUG) icvSeekTimeAVI_XINE ... start\n" );
537 #endif
538 
539 // not needed tnx to asserts...
540     // we need a valid capture context and it's stream to seek through
541 //	if ( !capture || !capture->stream ) return 0;
542 
543     if ( capture->seekable )
544     {
545         /// use xinelib's seek functionality
546         if ( xine_play( capture->stream, 0, t ) )
547         {
548             capture->frame_number = ( int ) ( ( float ) t * capture->frame_rate / 1000 );
549 #ifndef NDEBUG
550             fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... end\n" );
551 #endif
552             return 1;
553         }
554         else
555         {
556 #ifndef NDEBUG
557             fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... failed!\n" );
558 #endif
559             return 0;
560         }
561     }
562     else
563     {
564         int new_frame = ( int ) ( ( float ) t * capture->frame_rate / 1000 );
565 #ifndef NDEBUG
566         fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ....end\n" );
567 #endif
568         return icvOldSeekFrameAVI_XINE( capture, new_frame );
569     }
570 }
571 
572 
icvSeekRatioAVI_XINE(CvCaptureAVI_XINE * capture,double ratio)573 static int icvSeekRatioAVI_XINE( CvCaptureAVI_XINE* capture, double ratio )
574 {
575 #ifndef NDEBUG
576     fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... start\n" );
577 #endif
578 
579     OPENCV_ASSERT ( capture,
580                         "icvSeekRatioAVI_XINE( CvCaptureAVI_XINE *, double )", "illegal capture");
581     OPENCV_ASSERT ( capture->stream,
582                         "icvSeekRatioAVI_XINE( CvCaptureAVI_XINE *, double )", "illegal capture->stream");
583     OPENCV_ASSERT ( capture->vo_port,
584                         "icvSeekRatioAVI_XINE( CvCaptureAVI_XINE *, double )", "illegal capture->vo_port");
585 
586 // not needed tnx to asserts...
587     // we need a valid capture context and it's stream to seek through
588 //	if ( !capture || !capture->stream ) return 0;
589 
590     /// ratio must be [0..1]
591     if ( ratio > 1 || ratio < 0 ) return 0;
592 
593     if ( capture->seekable )
594     {
595     // TODO: FIX IT, DOESN'T WORK PROPERLY, YET...!
596         int pos_t, pos_l, length;
597         xine_get_pos_length( capture->stream, &pos_l, &pos_t, &length );
598         fprintf( stderr, "ratio on GetProperty(): %d\n", pos_l );
599 
600         /// use xinelib's seek functionality
601         if ( xine_play( capture->stream, (int)(ratio*(float)length), 0 ) )
602         {
603             capture->frame_number = ( int ) ( ratio*length / capture->frame_duration );
604         }
605         else
606         {
607 #ifndef NDEBUG
608             fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... failed!\n" );
609 #endif
610             return 0;
611         }
612     }
613     else
614     {
615         /// TODO: fill it !
616         fprintf( stderr, "icvSeekRatioAVI_XINE(): Seek not supported by stream !\n" );
617         fprintf( stderr, "icvSeekRatioAVI_XINE(): (seek in stream with NO seek support NOT implemented...yet!)\n" );
618 #ifndef NDEBUG
619         fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... failed!\n" );
620 #endif
621         return 0;
622     }
623 
624 #ifndef NDEBUG
625     fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... end!\n" );
626 #endif
627     return 1;
628 }
629 
630 
icvGetPropertyAVI_XINE(CvCaptureAVI_XINE * capture,int property_id)631 static double icvGetPropertyAVI_XINE( CvCaptureAVI_XINE* capture, int property_id )
632 {
633 #ifndef NDEBUG
634     fprintf( stderr, "(DEBUG) icvGetPropertyAVI_XINE ... start\n" );
635 #endif
636 
637     OPENCV_ASSERT ( capture,
638                         "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture");
639     OPENCV_ASSERT ( capture->stream,
640                         "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
641     OPENCV_ASSERT ( capture->vo_port,
642                         "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->vo_port");
643     OPENCV_ASSERT ( capture->xine,
644                         "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->xine");
645     OPENCV_ASSERT ( capture->bgr_frame,
646                         "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->bgr_frame");
647 
648 // not needed tnx to asserts...
649     // we need a valid capture context and it's stream to seek through
650 //	if ( !capture || !capture->stream || !capture->bgr_frame || !capture->xine || !capture->vo_port ) return 0
651 
652     int pos_t, pos_l, length;
653     xine_get_pos_length( capture->stream, &pos_l, &pos_t, &length );
654     fprintf( stderr, "ratio on GetProperty(): %i\n", pos_l );
655 
656     switch ( property_id )
657     {
658             /// return actual position in msec
659             case CV_CAP_PROP_POS_MSEC:
660             if ( !capture->seekable )
661             {
662                 fprintf( stderr, "(ERROR) GetPropertyAVI_XINE(CV_CAP_PROP_POS_MSEC:\n" );
663                 fprintf( stderr, "	Stream is NOT seekable, so position info may NOT be valid !!\n" );
664             }
665             return pos_t;
666 
667             /// return actual frame number
668             case CV_CAP_PROP_POS_FRAMES:
669             /// we insist the capture->frame_number to be remain updated !!!!
670             return capture->frame_number;
671 
672             /// return actual position ratio in the range [0..1] depending on
673             /// the total length of the stream and the actual position
674             case CV_CAP_PROP_POS_AVI_RATIO:
675             if ( !capture->seekable )
676             {
677                 fprintf( stderr, "(ERROR) GetPropertyAVI_XINE(CV_CAP_PROP_POS_AVI_RATIO:\n" );
678                 fprintf( stderr, "	Stream is NOT seekable, so ratio info may NOT be valid !!\n" );
679             }
680             if ( length == 0 ) break;
681             else return pos_l / 65535;
682 
683 
684             /// return width of image source
685             case CV_CAP_PROP_FRAME_WIDTH:
686             return capture->size.width;
687 
688             /// return height of image source
689             case CV_CAP_PROP_FRAME_HEIGHT:
690             return capture->size.height;
691 
692             /// return framerate of stream
693             case CV_CAP_PROP_FPS:
694             if ( !capture->seekable )
695             {
696                 fprintf( stderr, "(ERROR) GetPropertyAVI_XINE(CV_CAP_PROP_FPS:\n" );
697                 fprintf( stderr, "	Stream is NOT seekable, so FPS info may NOT be valid !!\n" );
698             }
699             return capture->frame_rate;
700 
701             /// return four-character-code (FOURCC) of source's codec
702             case CV_CAP_PROP_FOURCC:
703             return ( double ) xine_get_stream_info( capture->stream, XINE_STREAM_INFO_VIDEO_FOURCC );
704     }
705 
706 #ifndef NDEBUG
707     fprintf( stderr, "(DEBUG) icvGetPropertyAVI_XINE ... failed!\n" );
708 #endif
709 
710     return 0;
711 }
712 
713 
icvSetPropertyAVI_XINE(CvCaptureAVI_XINE * capture,int property_id,double value)714 static int icvSetPropertyAVI_XINE( CvCaptureAVI_XINE* capture,
715                                    int property_id, double value )
716 {
717 #ifndef NDEBUG
718     fprintf( stderr, "(DEBUG) icvSetPropertyAVI_XINE ... start\n" );
719 #endif
720 
721     OPENCV_ASSERT ( capture,
722                         "icvSetPropertyAVI_XINE( CvCaptureAVI_XINE *, int, double )", "illegal capture");
723     OPENCV_ASSERT ( capture->stream,
724                         "icvGetPropericvSetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
725     OPENCV_ASSERT ( capture->vo_port,
726                         "icvSetPropertyAVI_XINE( CvCaptureAVI_XINE *, int, double )", "illegal capture->vo_port");
727 
728 // not needed tnx to asserts...
729     // we need a valid capture context and it's stream to seek through
730 //	if ( !capture || !capture->stream || !capture->bgr_frame || !capture->xine || !capture->vo_port ) return 0
731 
732 #ifndef NDEBUG
733     fprintf( stderr, "(DEBUG) icvSetPropertyAVI_XINE: seeking to value %f ... ", value );
734 #endif
735 
736     switch ( property_id )
737     {
738             /// set (seek to) position in msec
739             case CV_CAP_PROP_POS_MSEC:
740             return icvSeekTimeAVI_XINE( capture, ( int ) value );
741 
742             /// set (seek to) frame number
743             case CV_CAP_PROP_POS_FRAMES:
744             return icvSeekFrameAVI_XINE( capture, ( int ) value );
745 
746             /// set (seek to) position ratio in the range [0..1] depending on
747             /// the total length of the stream and the actual position
748             case CV_CAP_PROP_POS_AVI_RATIO:
749             return icvSeekRatioAVI_XINE( capture, value );
750 
751             default:
752 #ifndef NDEBUG
753             fprintf( stderr, "(DEBUG) icvSetPropertyAVI_XINE ... failed!\n" );
754 #endif
755 
756             return 0;
757     }
758 }
759 
760 
icvCaptureFromFile_XINE(const char * filename)761 static CvCaptureAVI_XINE* icvCaptureFromFile_XINE( const char* filename )
762 {
763     // construct capture struct
764     CvCaptureAVI_XINE * capture = ( CvCaptureAVI_XINE* ) cvAlloc ( sizeof ( CvCaptureAVI_XINE ) );
765     memset( capture, 0, sizeof ( CvCaptureAVI_XINE ) );
766 
767     // initialize XINE
768     if ( !icvOpenAVI_XINE( capture, filename ) )
769         return 0;
770 
771     OPENCV_ASSERT ( capture,
772                         "cvCaptureFromFile_XINE( const char * )", "couldn't create capture");
773 
774     return capture;
775 
776 }
777 
778 
779 
780 class CvCaptureAVI_XINE_CPP : public CvCapture
781 {
782 public:
CvCaptureAVI_XINE_CPP()783     CvCaptureAVI_XINE_CPP() { captureXINE = 0; }
~CvCaptureAVI_XINE_CPP()784     virtual ~CvCaptureAVI_XINE_CPP() { close(); }
785 
786     virtual bool open( const char* filename );
787     virtual void close();
788 
789     virtual double getProperty(int) const;
790     virtual bool setProperty(int, double);
791     virtual bool grabFrame();
792     virtual IplImage* retrieveFrame(int);
793 protected:
794 
795     CvCaptureAVI_XINE* captureXINE;
796 };
797 
open(const char * filename)798 bool CvCaptureAVI_XINE_CPP::open( const char* filename )
799 {
800     close();
801     captureXINE = icvCaptureFromFile_XINE(filename);
802     return captureXINE != 0;
803 }
804 
close()805 void CvCaptureAVI_XINE_CPP::close()
806 {
807     if( captureXINE )
808     {
809         icvCloseAVI_XINE( captureXINE );
810         cvFree( &captureXINE );
811     }
812 }
813 
grabFrame()814 bool CvCaptureAVI_XINE_CPP::grabFrame()
815 {
816     return captureXINE ? icvGrabFrameAVI_XINE( captureXINE ) != 0 : false;
817 }
818 
retrieveFrame(int)819 IplImage* CvCaptureAVI_XINE_CPP::retrieveFrame(int)
820 {
821     return captureXINE ? (IplImage*)icvRetrieveFrameAVI_XINE( captureXINE, 0 ) : 0;
822 }
823 
getProperty(int propId) const824 double CvCaptureAVI_XINE_CPP::getProperty( int propId ) const
825 {
826     return captureXINE ? icvGetPropertyAVI_XINE( captureXINE, propId ) : 0;
827 }
828 
setProperty(int propId,double value)829 bool CvCaptureAVI_XINE_CPP::setProperty( int propId, double value )
830 {
831     return captureXINE ? icvSetPropertyAVI_XINE( captureXINE, propId, value ) != 0 : false;
832 }
833 
cvCreateFileCapture_XINE(const char * filename)834 CvCapture* cvCreateFileCapture_XINE(const char* filename)
835 {
836     CvCaptureAVI_XINE_CPP* capture = new CvCaptureAVI_XINE_CPP;
837 
838     if( capture->open(filename))
839         return capture;
840 
841     delete capture;
842     return 0;
843 }
844 
845 
846 #undef NDEBUG
847