267615ad907f2de71c4d4ecae2a39e7576175870
[opencv] / otherlibs / highgui / cvcap_xine.cpp
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 "_highgui.h"
50
51 // required to enable some functions used here...
52 #define XINE_ENABLE_EXPERIMENTAL_FEATURES
53
54 #include <cv.h>
55 #include <cassert>
56
57 extern "C"
58 {
59 #include <xine.h>
60         //#include <xine/xineutils.h>
61
62         // forward declaration from <xine/xineutils.h>
63         const char *xine_get_homedir( void );
64 }
65
66 typedef struct CvCaptureAVI_XINE
67 {
68         /// method call table
69         CvCaptureVTable * vtable;
70
71         xine_t * xine;
72         xine_stream_t * stream;
73         xine_video_port_t * vo_port;
74
75         /// frame returned by xine_get_next_video_frame()
76         xine_video_frame_t xine_frame;
77
78         IplImage        * yuv_frame;
79         IplImage        * bgr_frame;
80
81         /// image dimansions of the input stream.
82         CvSize  size;
83
84         /// framenumber of the last frame received from xine_get_next_video_frame().
85         /// note: always keep this value updated !!!!
86         int     frame_number;
87
88         /// framerate of the opened stream
89         double  frame_rate;
90
91         /// duration of a frame in stream
92         double  frame_duration;
93
94         /// indicated if input is seekable
95         bool    seekable;
96
97 }
98 CvCaptureAVI_XINE;
99
100
101 // 4:2:2 interleaved -> BGR
102 static void icvYUY2toBGR( CvCaptureAVI_XINE * capture )
103 {
104         uint8_t * v     = capture->xine_frame.data;
105         int offset;
106         for ( int y = 0; y < capture->yuv_frame->height; y++ )
107         {
108                 offset  = y * capture->yuv_frame->widthStep;
109
110                 for ( int x = 0; x < capture->yuv_frame->width; x++, offset += 3 )
111                 {
112                         capture->yuv_frame->imageData[ offset + 1 ] = v[ 3 ];
113                         capture->yuv_frame->imageData[ offset + 2 ] = v[ 1 ];
114                         if ( x & 1 )
115                         {
116                                 capture->yuv_frame->imageData[ offset ] = v[ 2 ];
117                                 v += 4;
118                         }
119                         else
120                         {
121                                 capture->yuv_frame->imageData[ offset ] = v[ 0 ];
122                         }
123                 }
124         }
125
126         // convert to BGR
127         cvCvtColor( capture->yuv_frame, capture->bgr_frame, CV_YCrCb2BGR );
128 }
129
130
131 // 4:2:0 planary -> BGR
132 static void icvYV12toBGR( CvCaptureAVI_XINE * capture )
133 {
134         IplImage * yuv  = capture->yuv_frame;
135         int     w_Y     = capture->size.width;
136         int     h_Y     = capture->size.height;
137
138         int     w_UV    = w_Y >> 1;
139
140         int     size_Y  = w_Y * h_Y;
141         int     size_UV = size_Y / 4;
142
143         int     line    = yuv->widthStep;
144
145         uint8_t * addr_Y = capture->xine_frame.data;
146         uint8_t * addr_U = addr_Y + size_Y;
147         uint8_t * addr_V = addr_U + size_UV;
148
149         // YYYY..UU.VV. -> BGRBGRBGR...
150         for ( int y = 0; y < h_Y; y++ )
151         {
152                 int offset = y * line;
153                 for ( int x = 0; x < w_Y; x++, offset += 3 )
154                 {
155                         /*
156                         if ( x&1 )
157                         {
158                                 addr_U++; addr_V++;
159                         }
160                         */
161                         int one_zero = x & 1;
162                         addr_U += one_zero;
163                         addr_V += one_zero;
164
165                         yuv->imageData[ offset ] = *( addr_Y++ );
166                         yuv->imageData[ offset + 1 ] = *addr_U;
167                         yuv->imageData[ offset + 2 ] = *addr_V;
168                 }
169
170                 if ( y & 1 )
171                 {
172                         addr_U -= w_UV;
173                         addr_V -= w_UV;
174                 }
175         }
176
177         /* convert to BGR */
178         cvCvtColor( capture->yuv_frame, capture->bgr_frame, CV_YCrCb2BGR );
179 }
180
181 static void icvCloseAVI_XINE( CvCaptureAVI_XINE* capture )
182 {
183         xine_free_video_frame( capture->vo_port, &capture->xine_frame );
184
185         if ( capture->yuv_frame ) cvReleaseImage( &capture->yuv_frame );
186         if ( capture->bgr_frame ) cvReleaseImage( &capture->bgr_frame );
187
188         xine_close( capture->stream );
189         //      xine_dispose( capture->stream );
190
191         if ( capture->vo_port ) xine_close_video_driver( capture->xine, capture->vo_port );
192
193         xine_exit( capture->xine );
194 }
195
196
197 /**
198  * CHECKS IF THE STREAM IN * capture IS SEEKABLE.
199 **/
200 static void icvCheckSeekAVI_XINE( CvCaptureAVI_XINE * capture )
201 {
202         OPENCV_ASSERT ( capture,                        "icvCheckSeekAVI_XINE( CvCaptureAVI_XINE* )", "illegal capture");
203         OPENCV_ASSERT ( capture->stream,
204                         "icvCheckSeekAVI_XINE( CvCaptureAVI_XINE* )", "illegal capture->stream");
205         OPENCV_ASSERT ( capture->vo_port,
206                         "icvCheckSeekAVI_XINE( CvCaptureAVI_XINE* )", "illegal capture->vo_port");
207
208 #ifndef NDEBUG
209         fprintf( stderr, "(DEBUG) icvCheckSeekAVI_XINE ... start\n" );
210 #endif
211
212         // temp. frame for testing.
213         xine_video_frame_t tmp;
214         // try to seek to a future frame...
215         xine_play( capture->stream, 0, 300 ); /* 300msec */
216         // try to receive the frame...
217         xine_get_next_video_frame( capture->vo_port, &tmp );
218         // if the framenumber is still 0, we can't use the xine seek functionality
219         capture->seekable = ( tmp.frame_number != 0 );
220         // reset stream
221         xine_play( capture->stream, 0, 0 );
222         // release xine_frame
223         xine_free_video_frame( capture->vo_port, &tmp );
224
225 #ifndef NDEBUG
226         if ( capture->seekable )
227                 fprintf( stderr, "(DEBUG) icvCheckSeekAVI_XINE: Input is seekable, using XINE seek implementation.\n" );
228         else
229                 fprintf( stderr, "(DEBUG) icvCheckSeekAVI_XINE: Input is NOT seekable, using fallback function.\n" );
230         
231         fprintf( stderr, "(DEBUG) icvCheckSeekAVI_XINE ... end\n" );
232 #endif
233 }
234
235
236 static int icvOpenAVI_XINE( CvCaptureAVI_XINE* capture, const char* filename )
237 {
238 #ifndef NDEBUG
239         fprintf( stderr, "(DEBUG) icvOpenAVI_XINE ... start\n" );
240 #endif
241
242         char configfile[ 2048 ];
243
244         capture->xine = xine_new();
245         sprintf( configfile, "%s%s", xine_get_homedir(), "/.xine/config" );
246
247         xine_config_load( capture->xine, configfile );
248         xine_init( capture->xine );
249
250         xine_engine_set_param( capture->xine, 0, 0 );
251         capture->vo_port = xine_new_framegrab_video_port( capture->xine );
252         if ( capture->vo_port == NULL )
253         {
254                 printf( "(ERROR)icvOpenAVI_XINE(): Unable to initialize video driver.\n" );
255                 return 0;
256         }
257
258         capture->stream = xine_stream_new( capture->xine, NULL, capture->vo_port );
259
260         if ( !xine_open( capture->stream, filename ) )
261         {
262                 printf( "(ERROR)icvOpenAVI_XINE(): Unable to open source '%s'\n", filename );
263                 return 0;
264         }
265         // reset stream...
266         xine_play( capture->stream, 0, 0 );
267         
268
269         // initialize some internals...
270         capture->frame_number = 0;
271
272         if ( !xine_get_next_video_frame( capture->vo_port, &capture->xine_frame ) )
273         {
274 #ifndef NDEBUG
275                 fprintf( stderr, "(DEBUG) icvOpenAVI_XINE ... failed!\n" );
276 #endif
277                 return 0;
278         }
279
280         capture->size = cvSize( capture->xine_frame.width, capture->xine_frame.height );
281         capture->yuv_frame = cvCreateImage( capture->size, IPL_DEPTH_8U, 3 );
282         capture->bgr_frame = cvCreateImage( capture->size, IPL_DEPTH_8U, 3 );
283
284         xine_free_video_frame( capture->vo_port, &capture->xine_frame );
285         capture->xine_frame.data[ 0 ] = 0;
286
287         icvCheckSeekAVI_XINE( capture );
288
289         capture->frame_duration = xine_get_stream_info( capture->stream, XINE_STREAM_INFO_FRAME_DURATION ) / 90.;
290         capture->frame_rate = 1000 / capture->frame_duration;
291
292 #ifndef NDEBUG
293         fprintf( stderr, "(DEBUG) frame_duration = %f, framerate = %f\n", capture->frame_duration, capture->frame_rate );
294 #endif
295         
296         OPENCV_ASSERT ( capture->yuv_frame,
297                         "icvOpenAVI_XINE( CvCaptureAVI_XINE *, const char *)", "couldn't create yuv frame");
298                         
299         OPENCV_ASSERT ( capture->bgr_frame,
300                         "icvOpenAVI_XINE( CvCaptureAVI_XINE *, const char *)", "couldn't create bgr frame");
301                         
302 #ifndef NDEBUG
303         fprintf( stderr, "(DEBUG) icvOpenAVI_XINE ... end\n" );
304 #endif
305         return 1;
306 }
307
308
309 static int icvGrabFrameAVI_XINE( CvCaptureAVI_XINE* capture )
310 {
311 #ifndef NDEBUG
312         fprintf( stderr, "(DEBUG) icvGrabFrameAVI_XINE ... start\n" );
313 #endif
314
315         OPENCV_ASSERT ( capture,
316                         "icvGrabFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture");
317         OPENCV_ASSERT ( capture->vo_port,
318                         "icvGrabFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture->vo_port");
319
320         int res = xine_get_next_video_frame( capture->vo_port, &capture->xine_frame );
321
322         /* always keep internal framenumber updated !!! */
323         if ( res ) capture->frame_number++;
324
325 #ifndef NDEBUG
326         fprintf( stderr, "(DEBUG) icvGrabFrameAVI_XINE ... end\n" );
327 #endif
328         return res;
329 }
330
331
332 static const IplImage* icvRetrieveFrameAVI_XINE( CvCaptureAVI_XINE* capture )
333 {
334 #ifndef NDEBUG
335         fprintf( stderr, "(DEBUG) icvRetrieveFrameAVI_XINE ... start\n" );
336 #endif
337
338         OPENCV_ASSERT ( capture,
339                         "icvRetrieveFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture");
340         OPENCV_ASSERT ( capture->stream,
341                         "icvRetrieveFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture->stream");
342         OPENCV_ASSERT ( capture->vo_port,
343                         "icvRetrieveFrameAVI_XINE( CvCaptureAVI_XINE * )", "illegal capture->vo_port");
344
345         /* no frame grabbed yet? so let's do it now! */
346         int res = 0;
347         if ( capture->xine_frame.data == 0 )
348         {
349                 res = icvGrabFrameAVI_XINE( capture );
350         }
351         else
352         {
353                 res = 1;
354         }
355
356         if ( res )
357         {
358                 switch ( capture->xine_frame.colorspace )
359                 {
360                                 case XINE_IMGFMT_YV12: icvYV12toBGR( capture );
361 #ifndef NDEBUG
362                                 printf( "(DEBUG)icvRetrieveFrameAVI_XINE: converted YV12 to BGR.\n" );
363 #endif
364                                 break;
365
366                                 case XINE_IMGFMT_YUY2: icvYUY2toBGR( capture );
367 #ifndef NDEBUG
368                                 printf( "(DEBUG)icvRetrieveFrameAVI_XINE: converted YUY2 to BGR.\n" );
369 #endif
370                                 break;
371                                 case XINE_IMGFMT_XVMC: printf( "(ERROR)icvRetrieveFrameAVI_XINE: XVMC format not supported!\n" );
372                                 break;
373
374                                 case XINE_IMGFMT_XXMC: printf( "(ERROR)icvRetrieveFrameAVI_XINE: XXMC format not supported!\n" );
375                                 break;
376
377                                 default: printf( "(ERROR)icvRetrieveFrameAVI_XINE: unknown color/pixel format!\n" );
378                 }
379
380                 /* always release last xine_frame, not needed anymore, but store its frame_number in *capture ! */
381                 xine_free_video_frame( capture->vo_port, &capture->xine_frame );
382                 capture->xine_frame.data = 0;
383
384 #ifndef NDEBUG
385                 fprintf( stderr, "(DEBUG) icvRetrieveFrameAVI_XINE ... end\n" );
386 #endif
387                 return capture->bgr_frame;
388         }
389
390 #ifndef NDEBUG
391         fprintf( stderr, "(DEBUG) icvRetrieveFrameAVI_XINE ... failed!\n" );
392 #endif
393         return 0;
394 }
395
396
397 /**
398  * THIS FUNCTION IS A FALLBACK FUNCTION FOR THE CASE THAT THE XINE SEEK IMPLEMENTATION
399  * DOESN'T WORK WITH THE ACTUAL INPUT. THIS FUNCTION IS ONLY USED IN THE CASE OF AN EMERGENCY,
400  * BECAUSE IT IS VERY SLOW !
401 **/
402 static int icvOldSeekFrameAVI_XINE( CvCaptureAVI_XINE* capture, int f )
403 {
404 #ifndef NDEBUG
405         fprintf( stderr, "(DEBUG) icvOldSeekFrameAVI_XINE ... start\n" );
406 #endif
407
408         OPENCV_ASSERT ( capture,
409                         "icvRetricvOldSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture");
410         OPENCV_ASSERT ( capture->stream,
411                         "icvOldSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
412         OPENCV_ASSERT ( capture->vo_port,
413                         "icvOldSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->vo_port");
414
415 // not needed tnx to asserts...                         
416         // we need a valid capture context and it's stream to seek through
417 //      if ( !capture || !capture->stream ) return 0;
418
419         // no need to seek if we are already there...
420         if ( f == capture->frame_number )
421         {
422 #ifndef NDEBUG
423                 fprintf( stderr, "(DEBUG) icvOldSeekFrameAVI_XINE ... end\n" );
424 #endif
425                 return 1;
426         }
427         // if the requested position is behind out actual position,
428         // we just need to read the remaining amount of frames until we are there.
429         else if ( f > capture->frame_number )
430         {
431                 for ( ;capture->frame_number < f;capture->frame_number++ )
432                         /// un-increment framenumber grabbing failed
433                         if ( !xine_get_next_video_frame( capture->vo_port, &capture->xine_frame ) )
434                         {
435                                 capture->frame_number--;
436                                 break;
437                         }
438                         else
439                         {
440                                 xine_free_video_frame( capture->vo_port, &capture->xine_frame );
441                         }
442         }
443         // otherwise we need to reset the stream and
444         // start reading frames from the beginning.
445         else // f < capture->frame_number
446         {
447                 /// reset stream, should also work with non-seekable input
448                 xine_play( capture->stream, 0, 0 );
449                 /// read frames until we are at the requested frame
450                 for ( capture->frame_number = 0; capture->frame_number < f; capture->frame_number++ )
451                         /// un-increment last framenumber if grabbing failed
452                         if ( !xine_get_next_video_frame( capture->vo_port, &capture->xine_frame ) )
453                         {
454                                 capture->frame_number--;
455                                 break;
456                         }
457                         else
458                         {
459                                 xine_free_video_frame( capture->vo_port, &capture->xine_frame );
460                         }
461         }
462
463
464 #ifndef NDEBUG
465         fprintf( stderr, "(DEBUG) icvOldSeekFrameAVI_XINE ... end\n" );
466 #endif
467         return ( f == capture->frame_number ) ? 1 : 0;
468 }
469
470
471 static int icvSeekFrameAVI_XINE( CvCaptureAVI_XINE* capture, int f )
472 {
473 #ifndef NDEBUG
474         fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... start\n" );
475 #endif
476
477         OPENCV_ASSERT ( capture,
478                         "icvSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture");
479         OPENCV_ASSERT ( capture->stream,
480                         "icvSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
481         OPENCV_ASSERT ( capture->vo_port,
482                         "icvSeekFrameAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->vo_port");
483
484 // not needed tnx to asserts...                         
485         // we need a valid capture context and it's stream to seek through
486 //      if ( !capture || !capture->stream ) return 0;
487
488         if ( capture->seekable )
489         {
490
491                 /// use xinelib's seek functionality
492                 int new_time = ( int ) ( ( f + 1 ) * ( float ) capture->frame_duration );
493
494 #ifndef NDEBUG
495                 fprintf( stderr, "(DEBUG) calling xine_play()" );
496 #endif
497                 if ( xine_play( capture->stream, 0, new_time ) )
498                 {
499 #ifndef NDEBUG
500                         fprintf( stderr, "ok\n" );
501                         fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... end\n" );
502 #endif
503                         capture->frame_number = f;
504                         return 1;
505                 }
506                 else
507                 {
508 #ifndef NDEBUG
509                         fprintf( stderr, "failed\n" );
510                         fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... failed\n" );
511 #endif
512                         return 0;
513                 }
514         }
515         else
516         {
517 #ifndef NDEBUG
518                 fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... end\n" );
519 #endif
520                 return icvOldSeekFrameAVI_XINE( capture, f );
521         }
522 }
523
524
525 static int icvSeekTimeAVI_XINE( CvCaptureAVI_XINE* capture, int t )
526 {
527 #ifndef NDEBUG
528         fprintf( stderr, "(DEBUG) icvSeekTimeAVI_XINE ... start\n" );
529 #endif
530
531         OPENCV_ASSERT ( capture,
532                         "icvSeekTimeAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture");
533         OPENCV_ASSERT ( capture->stream,
534                         "icvSeekTimeAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
535         OPENCV_ASSERT ( capture->vo_port,
536                         "icvSeekTimeAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->vo_port");
537                         
538 #ifndef NDEBUG
539         fprintf( stderr, "(DEBUG) icvSeekTimeAVI_XINE ... start\n" );
540 #endif  
541
542 // not needed tnx to asserts...                         
543         // we need a valid capture context and it's stream to seek through
544 //      if ( !capture || !capture->stream ) return 0;
545
546         if ( capture->seekable )
547         {
548                 /// use xinelib's seek functionality
549                 if ( xine_play( capture->stream, 0, t ) )
550                 {
551                         capture->frame_number = ( int ) ( ( float ) t * capture->frame_rate / 1000 );
552 #ifndef NDEBUG                  
553                         fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... end\n" );
554 #endif
555                         return 1;
556                 }
557                 else
558                 {
559 #ifndef NDEBUG          
560                         fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ... failed!\n" );
561 #endif
562                         return 0;
563                 }
564         }
565         else
566         {
567                 int new_frame = ( int ) ( ( float ) t * capture->frame_rate / 1000 );
568 #ifndef NDEBUG                          
569                 fprintf( stderr, "(DEBUG) icvSeekFrameAVI_XINE ....end\n" );
570 #endif
571                 return icvOldSeekFrameAVI_XINE( capture, new_frame );
572         }
573 }
574
575
576 static int icvSeekRatioAVI_XINE( CvCaptureAVI_XINE* capture, double ratio )
577 {
578 #ifndef NDEBUG
579         fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... start\n" );
580 #endif
581
582         OPENCV_ASSERT ( capture,
583                         "icvSeekRatioAVI_XINE( CvCaptureAVI_XINE *, double )", "illegal capture");
584         OPENCV_ASSERT ( capture->stream,
585                         "icvSeekRatioAVI_XINE( CvCaptureAVI_XINE *, double )", "illegal capture->stream");
586         OPENCV_ASSERT ( capture->vo_port,
587                         "icvSeekRatioAVI_XINE( CvCaptureAVI_XINE *, double )", "illegal capture->vo_port");
588
589 // not needed tnx to asserts...                         
590         // we need a valid capture context and it's stream to seek through
591 //      if ( !capture || !capture->stream ) return 0;
592
593         /// ratio must be [0..1]
594         if ( ratio > 1 || ratio < 0 ) return 0;
595
596         if ( capture->seekable )
597         {
598         // TODO: FIX IT, DOESN'T WORK PROPERLY, YET...!
599                 int pos_t, pos_l, length;
600                 xine_get_pos_length( capture->stream, &pos_l, &pos_t, &length );
601                 fprintf( stderr, "ratio on GetProperty(): %n\n", pos_l );
602
603                 /// use xinelib's seek functionality
604                 if ( xine_play( capture->stream, (int)(ratio*(float)length), 0 ) )
605                 {
606                         capture->frame_number = ( int ) ( ratio*length / capture->frame_duration );
607                 }
608                 else
609                 {
610 #ifndef NDEBUG
611                         fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... failed!\n" );
612 #endif
613                         return 0;
614                 }
615         }
616         else
617         {
618                 /// TODO: fill it !
619                 fprintf( stderr, "icvSeekRatioAVI_XINE(): Seek not supported by stream !\n" );
620                 fprintf( stderr, "icvSeekRatioAVI_XINE(): (seek in stream with NO seek support NOT implemented...yet!)\n" );
621 #ifndef NDEBUG
622                 fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... failed!\n" );
623 #endif
624                 return 0;
625         }
626
627 #ifndef NDEBUG
628         fprintf( stderr, "(DEBUG) icvSeekRatioAVI_XINE ... end!\n" );
629 #endif
630         return 1;
631 }
632
633
634 static double icvGetPropertyAVI_XINE( CvCaptureAVI_XINE* capture, int property_id )
635 {
636 #ifndef NDEBUG
637         fprintf( stderr, "(DEBUG) icvGetPropertyAVI_XINE ... start\n" );
638 #endif
639
640         OPENCV_ASSERT ( capture,
641                         "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture");
642         OPENCV_ASSERT ( capture->stream,
643                         "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
644         OPENCV_ASSERT ( capture->vo_port,
645                         "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->vo_port");
646         OPENCV_ASSERT ( capture->xine,
647                         "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->xine");
648         OPENCV_ASSERT ( capture->bgr_frame,
649                         "icvGetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->bgr_frame");
650
651 // not needed tnx to asserts...                         
652         // we need a valid capture context and it's stream to seek through
653 //      if ( !capture || !capture->stream || !capture->bgr_frame || !capture->xine || !capture->vo_port ) return 0
654
655         int pos_t, pos_l, length;
656         xine_get_pos_length( capture->stream, &pos_l, &pos_t, &length );
657         fprintf( stderr, "ratio on GetProperty(): %i\n", pos_l );
658
659         switch ( property_id )
660         {
661                         /// return actual position in msec
662                         case CV_CAP_PROP_POS_MSEC:
663                         if ( !capture->seekable )
664                         {
665                                 fprintf( stderr, "(ERROR) GetPropertyAVI_XINE(CV_CAP_PROP_POS_MSEC:\n" );
666                                 fprintf( stderr, "      Stream is NOT seekable, so position info may NOT be valid !!\n" );
667                         }
668                         return pos_t;
669
670                         /// return actual frame number
671                         case CV_CAP_PROP_POS_FRAMES:
672                         /// we insist the capture->frame_number to be remain updated !!!!
673                         return capture->frame_number;
674
675                         /// return actual position ratio in the range [0..1] depending on
676                         /// the total length of the stream and the actual position
677                         case CV_CAP_PROP_POS_AVI_RATIO:
678                         if ( !capture->seekable )
679                         {
680                                 fprintf( stderr, "(ERROR) GetPropertyAVI_XINE(CV_CAP_PROP_POS_AVI_RATIO:\n" );
681                                 fprintf( stderr, "      Stream is NOT seekable, so ratio info may NOT be valid !!\n" );
682                         }
683                         if ( length == 0 ) break;
684                         else return pos_l / 65535;
685
686
687                         /// return width of image source
688                         case CV_CAP_PROP_FRAME_WIDTH:
689                         return capture->size.width;
690
691                         /// return height of image source
692                         case CV_CAP_PROP_FRAME_HEIGHT:
693                         return capture->size.height;
694
695                         /// return framerate of stream
696                         case CV_CAP_PROP_FPS:
697                         if ( !capture->seekable )
698                         {
699                                 fprintf( stderr, "(ERROR) GetPropertyAVI_XINE(CV_CAP_PROP_FPS:\n" );
700                                 fprintf( stderr, "      Stream is NOT seekable, so FPS info may NOT be valid !!\n" );
701                         }
702                         return capture->frame_rate;
703
704                         /// return four-character-code (FOURCC) of source's codec
705                         case CV_CAP_PROP_FOURCC:
706                         return ( double ) xine_get_stream_info( capture->stream, XINE_STREAM_INFO_VIDEO_FOURCC );
707         }
708
709 #ifndef NDEBUG
710         fprintf( stderr, "(DEBUG) icvGetPropertyAVI_XINE ... failed!\n" );
711 #endif
712
713         return 0;
714 }
715
716
717 static int icvSetPropertyAVI_XINE( CvCaptureAVI_XINE* capture,
718                                    int property_id, double value )
719 {
720 #ifndef NDEBUG
721         fprintf( stderr, "(DEBUG) icvSetPropertyAVI_XINE ... start\n" );
722 #endif
723
724         OPENCV_ASSERT ( capture,
725                         "icvSetPropertyAVI_XINE( CvCaptureAVI_XINE *, int, double )", "illegal capture");
726         OPENCV_ASSERT ( capture->stream,
727                         "icvGetPropericvSetPropertyAVI_XINE( CvCaptureAVI_XINE *, int )", "illegal capture->stream");
728         OPENCV_ASSERT ( capture->vo_port,
729                         "icvSetPropertyAVI_XINE( CvCaptureAVI_XINE *, int, double )", "illegal capture->vo_port");
730
731 // not needed tnx to asserts...                         
732         // we need a valid capture context and it's stream to seek through
733 //      if ( !capture || !capture->stream || !capture->bgr_frame || !capture->xine || !capture->vo_port ) return 0
734
735 #ifndef NDEBUG
736         fprintf( stderr, "(DEBUG) icvSetPropertyAVI_XINE: seeking to value %f ... ", value );
737 #endif
738
739         switch ( property_id )
740         {
741                         /// set (seek to) position in msec
742                         case CV_CAP_PROP_POS_MSEC:
743                         return icvSeekTimeAVI_XINE( capture, ( int ) value );
744
745                         /// set (seek to) frame number
746                         case CV_CAP_PROP_POS_FRAMES:
747                         return icvSeekFrameAVI_XINE( capture, ( int ) value );
748
749                         /// set (seek to) position ratio in the range [0..1] depending on
750                         /// the total length of the stream and the actual position
751                         case CV_CAP_PROP_POS_AVI_RATIO:
752                         return icvSeekRatioAVI_XINE( capture, value );
753
754                         default:
755 #ifndef NDEBUG
756                         fprintf( stderr, "(DEBUG) icvSetPropertyAVI_XINE ... failed!\n" );
757 #endif
758                         
759                         return 0;
760         }
761 }
762
763
764 static CvCaptureVTable captureAVI_XINE_vtable =
765 {
766         6,
767         ( CvCaptureCloseFunc ) icvCloseAVI_XINE,
768         ( CvCaptureGrabFrameFunc ) icvGrabFrameAVI_XINE,
769         ( CvCaptureRetrieveFrameFunc ) icvRetrieveFrameAVI_XINE,
770         ( CvCaptureGetPropertyFunc ) icvGetPropertyAVI_XINE,
771         ( CvCaptureSetPropertyFunc ) icvSetPropertyAVI_XINE,
772         ( CvCaptureGetDescriptionFunc ) 0
773 };
774
775
776 CvCapture* cvCaptureFromFile_XINE( const char* filename )
777 {
778         // construct capture struct
779         CvCaptureAVI_XINE * capture = ( CvCaptureAVI_XINE* ) cvAlloc ( sizeof ( CvCaptureAVI_XINE ) );
780         memset( capture, 0, sizeof ( CvCaptureAVI_XINE ) );
781         capture->vtable = &captureAVI_XINE_vtable;
782
783         // initialize XINE
784         if ( !icvOpenAVI_XINE( capture, filename ) )
785                 return 0;
786
787         OPENCV_ASSERT ( capture,
788                         "cvCaptureFromFile_XINE( const char * )", "couldn't create capture");
789                 
790         return ( CvCapture* ) capture;
791
792 }
793
794 #undef NDEBUG