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