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