Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
204 chris 1
/*
2
 *   Revision: 5.2   Date: 2000/08/25
3
 *   Video capture subrutine for Linux/Video4Linux devices
4
 *   author: Nakazawa,Atsushi ( nakazawa@inolab.sys.es.osaka-u.ac.jp )
5
 *           Hirokazu Kato ( kato@sys.im.hiroshima-cu.ac.jp )
6
 *
7
 *   Modified by Wayne Piekarski (wayne@tinmith.net) - 2005/03/29
8
 *   Added support to automatically adjust camera parameters if needed
9
 *
10
 *   Revision: 5.3   Date: 2004/11/18
11
 *      Rev             Date            Who             Changes
12
 *      5.3            2004-11-18       RG              -adding patch done by Uwe Woessner for YUV support on V4L.
13
 *                                                      (Thanks a lot for this contribution !!)
14
 *                                                      -modify default video options
15
 *                                                      (no overhead if define externally)
16
 *                                                      -adding full V4L options support
17
 *                                                      -adding eyetoy support
18
 *
19
 */
20
#include <sys/ioctl.h>
21
#include <sys/types.h>
22
#include <sys/stat.h>
23
#include <sys/mman.h>
24
#include <fcntl.h>
25
#include <unistd.h>
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <linux/types.h>
30
#include <linux/videodev.h>
31
#include <AR/config.h>
32
#include <AR/ar.h>
33
#include <AR/video.h>
34
#include "ccvt.h"
35
#ifdef USE_EYETOY
36
#include "jpegtorgb.h" 
37
#endif
38
 
39
#define MAXCHANNEL   10
40
 
41
static AR2VideoParamT   *gVid = NULL;
42
 
43
int arVideoDispOption( void )
44
{
45
    return  ar2VideoDispOption();
46
}
47
 
48
int arVideoOpen( char *config )
49
{
50
    if( gVid != NULL ) {
51
        printf("Device has been opened!!\n");
52
        return -1;
53
    }
54
    gVid = ar2VideoOpen( config );
55
    if( gVid == NULL ) return -1;
56
 
57
    return 0;
58
}
59
 
60
int arVideoClose( void )
61
{
62
        int result;
63
 
64
    if( gVid == NULL ) return -1;
65
 
66
        result = ar2VideoClose(gVid);
67
        gVid = NULL;
68
    return (result);
69
}
70
 
71
int arVideoInqSize( int *x, int *y )
72
{
73
    if( gVid == NULL ) return -1;
74
 
75
    return ar2VideoInqSize( gVid, x, y );
76
}
77
 
78
ARUint8 *arVideoGetImage( void )
79
{
80
    if( gVid == NULL ) return NULL;
81
 
82
    return ar2VideoGetImage( gVid );
83
}
84
 
85
int arVideoCapStart( void )
86
{
87
    if( gVid == NULL ) return -1;
88
 
89
    return ar2VideoCapStart( gVid );
90
}
91
 
92
int arVideoCapStop( void )
93
{
94
    if( gVid == NULL ) return -1;
95
 
96
    return ar2VideoCapStop( gVid );
97
}
98
 
99
int arVideoCapNext( void )
100
{
101
    if( gVid == NULL ) return -1;
102
 
103
    return ar2VideoCapNext( gVid );
104
}
105
 
106
/*-------------------------------------------*/
107
 
108
int ar2VideoDispOption( void )
109
{
110
    printf("ARVideo may be configured using one or more of the following options,\n");
111
    printf("separated by a space:\n\n");
112
    printf("DEVICE CONTROLS:\n");
113
    printf(" -dev=filepath\n");
114
    printf("    specifies device file.\n");
115
    printf(" -channel=N\n");
116
    printf("    specifies source channel.\n");
117
    printf(" -noadjust\n");
118
    printf("    prevent adjusting the width/height/channel if not suitable.\n");
119
    printf(" -width=N\n");
120
    printf("    specifies expected width of image.\n");
121
    printf(" -height=N\n");
122
    printf("    specifies expected height of image.\n");
123
    printf(" -palette=[RGB|YUV420P]\n");
124
    printf("    specifies the camera palette (WARNING:all are not supported on each camera !!).\n");
125
    printf("IMAGE CONTROLS (WARNING: every options are not supported by all camera !!):\n");
126
    printf(" -brightness=N\n");
127
    printf("    specifies brightness. (0.0 <-> 1.0)\n");
128
    printf(" -contrast=N\n");
129
    printf("    specifies contrast. (0.0 <-> 1.0)\n");
130
    printf(" -saturation=N\n");
131
    printf("    specifies saturation (color). (0.0 <-> 1.0) (for color camera only)\n");    
132
    printf(" -hue=N\n");
133
    printf("    specifies hue. (0.0 <-> 1.0) (for color camera only)\n");    
134
    printf(" -whiteness=N\n");
135
    printf("    specifies whiteness. (0.0 <-> 1.0) (REMARK: gamma for some drivers, otherwise for greyscale camera only)\n");
136
    printf(" -color=N\n");
137
    printf("    specifies saturation (color). (0.0 <-> 1.0) (REMARK: obsolete !! use saturation control)\n\n");
138
    printf("OPTION CONTROLS:\n");
139
    printf(" -mode=[PAL|NTSC|SECAM]\n");
140
    printf("    specifies TV signal mode (for tv/capture card).\n");
141
    printf("\n");
142
 
143
    return 0;
144
}
145
 
146
AR2VideoParamT *ar2VideoOpen( char *config_in )
147
{
148
    AR2VideoParamT            *vid;
149
    struct video_capability   vd;
150
    struct video_channel      vc[MAXCHANNEL];
151
    struct video_picture      vp;
152
    char                      *config, *a, line[256];
153
    int                       i;
154
    int                       adjust = 1;
155
 
156
 
157
        /* If no config string is supplied, we should use the environment variable, otherwise set a sane default */
158
        if (!config_in || !(config_in[0])) {
159
                /* None suppplied, lets see if the user supplied one from the shell */
160
                char *envconf = getenv ("ARTOOLKIT_CONFIG");
161
                if (envconf && envconf[0]) {
162
                        config = envconf;
163
                        printf ("Using config string from environment [%s].\n", envconf);
164
                } else {
165
                        config = NULL;
166
                        printf ("No video config string supplied, using defaults.\n");
167
                }
168
        } else {
169
                config = config_in;
170
                printf ("Using supplied video config string [%s].\n", config_in);
171
        }
172
 
173
    arMalloc( vid, AR2VideoParamT, 1 );
174
    strcpy( vid->dev, DEFAULT_VIDEO_DEVICE );
175
    vid->channel    = DEFAULT_VIDEO_CHANNEL;
176
    vid->width      = DEFAULT_VIDEO_WIDTH;
177
    vid->height     = DEFAULT_VIDEO_HEIGHT;
178
#if (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_BGRA)
179
    vid->palette = VIDEO_PALETTE_RGB32;     /* palette format */
180
#elif (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_BGR) || (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_RGB)
181
    vid->palette = VIDEO_PALETTE_RGB24;     /* palette format */
182
#endif
183
    vid->contrast   = -1.;
184
    vid->brightness = -1.;
185
    vid->saturation = -1.;
186
    vid->hue        = -1.;
187
    vid->whiteness  = -1.;
188
    vid->mode       = DEFAULT_VIDEO_MODE;
189
    vid->debug      = 0;
190
    vid->videoBuffer=NULL;
191
 
192
        a = config;
193
    if( a != NULL) {
194
        for(;;) {
195
            while( *a == ' ' || *a == '\t' ) a++;
196
            if( *a == '\0' ) break;
197
            if( strncmp( a, "-dev=", 5 ) == 0 ) {
198
                sscanf( a, "%s", line );
199
                if( sscanf( &line[5], "%s", vid->dev ) == 0 ) {
200
                    ar2VideoDispOption();
201
                    free( vid );
202
                    return 0;
203
                }
204
            }
205
            else if( strncmp( a, "-channel=", 9 ) == 0 ) {
206
                sscanf( a, "%s", line );
207
                if( sscanf( &line[9], "%d", &vid->channel ) == 0 ) {
208
                    ar2VideoDispOption();
209
                    free( vid );
210
                    return 0;
211
                }
212
            }
213
            else if( strncmp( a, "-width=", 7 ) == 0 ) {
214
                sscanf( a, "%s", line );
215
                if( sscanf( &line[7], "%d", &vid->width ) == 0 ) {
216
                    ar2VideoDispOption();
217
                    free( vid );
218
                    return 0;
219
                }
220
            }
221
            else if( strncmp( a, "-height=", 8 ) == 0 ) {
222
                sscanf( a, "%s", line );
223
                if( sscanf( &line[8], "%d", &vid->height ) == 0 ) {
224
                    ar2VideoDispOption();
225
                    free( vid );
226
                    return 0;
227
                }
228
            }
229
            else if( strncmp( a, "-palette=", 9 ) == 0 ) {
230
                if( strncmp( &a[9], "RGB", 3) == 0 ) {
231
#if (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_BGRA)
232
                  vid->palette = VIDEO_PALETTE_RGB32;     /* palette format */
233
#elif (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_BGR)|| (AR_DEFAULT_PIXEL_FORMAT == AR_PIXEL_FORMAT_RGB)
234
                  vid->palette = VIDEO_PALETTE_RGB24;     /* palette format */
235
#endif
236
                }
237
                else if( strncmp( &a[9], "YUV420P", 7 ) == 0 ) {
238
                  vid->palette = VIDEO_PALETTE_YUV420P;
239
                }
240
            }
241
            else if( strncmp ( a, "-noadjust", 9 ) == 0 ) {
242
              adjust = 0;
243
            }
244
            else if( strncmp( a, "-contrast=", 10 ) == 0 ) {
245
                sscanf( a, "%s", line );
246
                if( sscanf( &line[10], "%lf", &vid->contrast ) == 0 ) {
247
                    ar2VideoDispOption();
248
                    free( vid );
249
                    return 0;
250
                }
251
            }
252
            else if( strncmp( a, "-brightness=", 12 ) == 0 ) {
253
                sscanf( a, "%s", line );
254
                if( sscanf( &line[12], "%lf", &vid->brightness ) == 0 ) {
255
                    ar2VideoDispOption();
256
                    free( vid );
257
                    return 0;
258
                }
259
            }
260
            else if( strncmp( a, "-saturation=", 12 ) == 0 ) {
261
                sscanf( a, "%s", line );
262
                if( sscanf( &line[12], "%lf", &vid->saturation ) == 0 ) {
263
                    ar2VideoDispOption();
264
                    free( vid );
265
                    return 0;
266
                }
267
            }      
268
            else if( strncmp( a, "-hue=", 5 ) == 0 ) {
269
                sscanf( a, "%s", line );
270
                if( sscanf( &line[5], "%lf", &vid->hue ) == 0 ) {
271
                    ar2VideoDispOption();
272
                    free( vid );
273
                    return 0;
274
                }
275
            }  
276
            else if( strncmp( a, "-whiteness=", 11 ) == 0 ) {
277
                sscanf( a, "%s", line );
278
                if( sscanf( &line[11], "%lf", &vid->whiteness ) == 0 ) {
279
                    ar2VideoDispOption();
280
                    free( vid );
281
                    return 0;
282
                }
283
            }
284
            else if( strncmp( a, "-color=", 7 ) == 0 ) {
285
                sscanf( a, "%s", line );
286
                if( sscanf( &line[7], "%lf", &vid->saturation ) == 0 ) {
287
                    ar2VideoDispOption();
288
                    free( vid );
289
                    return 0;
290
                }
291
            }
292
            else if( strncmp( a, "-mode=", 6 ) == 0 ) {
293
                if( strncmp( &a[6], "PAL", 3 ) == 0 )        vid->mode = VIDEO_MODE_PAL;
294
                else if( strncmp( &a[6], "NTSC", 4 ) == 0 )  vid->mode = VIDEO_MODE_NTSC;
295
                else if( strncmp( &a[6], "SECAM", 5 ) == 0 ) vid->mode = VIDEO_MODE_SECAM;
296
                else {
297
                    ar2VideoDispOption();
298
                    free( vid );
299
                    return 0;
300
                }
301
            }
302
            else if( strncmp( a, "-debug", 6 ) == 0 ) {
303
                vid->debug = 1;
304
            }
305
            else {
306
                ar2VideoDispOption();
307
                free( vid );
308
                return 0;
309
            }
310
 
311
            while( *a != ' ' && *a != '\t' && *a != '\0') a++;
312
        }
313
    }
314
 
315
    vid->fd = open(vid->dev, O_RDWR);// O_RDONLY ?
316
    if(vid->fd < 0){
317
        printf("video device (%s) open failed\n",vid->dev);
318
        free( vid );
319
        return 0;
320
    }
321
 
322
    if(ioctl(vid->fd,VIDIOCGCAP,&vd) < 0){
323
        printf("ioctl failed\n");
324
        free( vid );
325
        return 0;
326
    }
327
 
328
    if( vid->debug ) {
329
        printf("=== debug info ===\n");
330
        printf("  vd.name      =   %s\n",vd.name);
331
        printf("  vd.channels  =   %d\n",vd.channels);
332
        printf("  vd.maxwidth  =   %d\n",vd.maxwidth);
333
        printf("  vd.maxheight =   %d\n",vd.maxheight);
334
        printf("  vd.minwidth  =   %d\n",vd.minwidth);
335
        printf("  vd.minheight =   %d\n",vd.minheight);
336
    }
337
 
338
    /* adjust capture size if needed */
339
    if (adjust)
340
      {
341
        if (vid->width >= vd.maxwidth)
342
          vid->width = vd.maxwidth;
343
        if (vid->height >= vd.maxheight)
344
          vid->height = vd.maxheight;
345
        if (vid->debug)
346
          printf ("arVideoOpen: width/height adjusted to (%d, %d)\n", vid->width, vid->height);
347
      }
348
 
349
    /* check capture size */
350
    if(vd.maxwidth  < vid->width  || vid->width  < vd.minwidth ||
351
       vd.maxheight < vid->height || vid->height < vd.minheight ) {
352
        printf("arVideoOpen: width or height oversize \n");
353
        free( vid );
354
        return 0;
355
    }
356
 
357
    /* adjust channel if needed */
358
    if (adjust)
359
      {
360
        if (vid->channel >= vd.channels)
361
          vid->channel = 0;
362
        if (vid->debug)
363
          printf ("arVideoOpen: channel adjusted to 0\n");
364
      }
365
 
366
    /* check channel */
367
    if(vid->channel < 0 || vid->channel >= vd.channels){
368
        printf("arVideoOpen: channel# is not valid. \n");
369
        free( vid );
370
        return 0;
371
    }
372
 
373
    if( vid->debug ) {
374
        printf("==== capture device channel info ===\n");
375
    }
376
 
377
    for(i = 0;i < vd.channels && i < MAXCHANNEL; i++){
378
        vc[i].channel = i;
379
        if(ioctl(vid->fd,VIDIOCGCHAN,&vc[i]) < 0){
380
            printf("error: acquireing channel(%d) info\n",i);
381
            free( vid );
382
            return 0;
383
        }
384
 
385
        if( vid->debug ) {
386
            printf("    channel = %d\n",  vc[i].channel);
387
            printf("       name = %s\n",  vc[i].name);
388
            printf("     tuners = %d",    vc[i].tuners);
389
 
390
            printf("       flag = 0x%08x",vc[i].flags);
391
            if(vc[i].flags & VIDEO_VC_TUNER)
392
                printf(" TUNER");
393
            if(vc[i].flags & VIDEO_VC_AUDIO)
394
                printf(" AUDIO");
395
            printf("\n");
396
 
397
            printf("     vc[%d].type = 0x%08x", i, vc[i].type);
398
            if(vc[i].type & VIDEO_TYPE_TV)
399
                printf(" TV");
400
            if(vc[i].type & VIDEO_TYPE_CAMERA)
401
                printf(" CAMERA");
402
            printf("\n");      
403
        }
404
    }
405
 
406
    /* select channel */
407
    vc[vid->channel].norm = vid->mode;       /* 0: PAL 1: NTSC 2:SECAM 3:AUTO */
408
    if(ioctl(vid->fd, VIDIOCSCHAN, &vc[vid->channel]) < 0){
409
        printf("error: selecting channel %d\n", vid->channel);
410
        free( vid );
411
        return 0;
412
    }
413
 
414
    if(ioctl(vid->fd, VIDIOCGPICT, &vp)) {
415
        printf("error: getting palette\n");
416
       free( vid );
417
       return 0;
418
    }
419
 
420
    if( vid->debug ) {
421
        printf("=== debug info ===\n");
422
        printf("  vp.brightness=   %d\n",vp.brightness);
423
        printf("  vp.hue       =   %d\n",vp.hue);
424
        printf("  vp.colour    =   %d\n",vp.colour);
425
        printf("  vp.contrast  =   %d\n",vp.contrast);
426
        printf("  vp.whiteness =   %d\n",vp.whiteness);
427
        printf("  vp.depth     =   %d\n",vp.depth);
428
        printf("  vp.palette   =   %d\n",vp.palette);
429
    }
430
 
431
    /* set video picture */
432
    if ((vid->brightness+1.)>0.001)
433
        vp.brightness   = 32767 * 2.0 *vid->brightness;
434
    if ((vid->contrast+1.)>0.001)
435
        vp.contrast   = 32767 * 2.0 *vid->contrast;
436
    if ((vid->hue+1.)>0.001)
437
        vp.hue   = 32767 * 2.0 *vid->hue;
438
    if ((vid->whiteness+1.)>0.001)
439
        vp.whiteness   = 32767 * 2.0 *vid->whiteness;
440
    if ((vid->saturation+1.)>0.001)
441
        vp.colour   = 32767 * 2.0 *vid->saturation;
442
    vp.depth      = 24;    
443
    vp.palette    = vid->palette;
444
 
445
    if(ioctl(vid->fd, VIDIOCSPICT, &vp)) {
446
        printf("error: setting configuration !! bad palette mode..\n TIPS:try other palette mode (or with new failure contact ARToolKit Developer)\n");
447
        free( vid );
448
        return 0;
449
    }
450
    if (vid->palette==VIDEO_PALETTE_YUV420P)
451
        arMalloc( vid->videoBuffer, ARUint8, vid->width*vid->height*3 );
452
 
453
    if( vid->debug ) {
454
        if(ioctl(vid->fd, VIDIOCGPICT, &vp)) {
455
            printf("error: getting palette\n");
456
            free( vid );
457
            return 0;
458
        }
459
        printf("=== debug info ===\n");
460
        printf("  vp.brightness=   %d\n",vp.brightness);
461
        printf("  vp.hue       =   %d\n",vp.hue);
462
        printf("  vp.colour    =   %d\n",vp.colour);
463
        printf("  vp.contrast  =   %d\n",vp.contrast);
464
        printf("  vp.whiteness =   %d\n",vp.whiteness);
465
        printf("  vp.depth     =   %d\n",vp.depth);
466
        printf("  vp.palette   =   %d\n",vp.palette);
467
    }
468
 
469
    /* get mmap info */
470
    if(ioctl(vid->fd,VIDIOCGMBUF,&vid->vm) < 0){
471
        printf("error: videocgmbuf\n");
472
        free( vid );
473
        return 0;
474
    }
475
 
476
    if( vid->debug ) {
477
        printf("===== Image Buffer Info =====\n");
478
        printf("   size   =  %d[bytes]\n", vid->vm.size);
479
        printf("   frames =  %d\n", vid->vm.frames);
480
    }
481
    if(vid->vm.frames < 2){
482
        printf("this device can not be supported by libARvideo.\n");
483
        printf("(vm.frames < 2)\n");
484
        free( vid );
485
        return 0;
486
    }
487
 
488
 
489
    /* get memory mapped io */
490
    if((vid->map = (ARUint8 *)mmap(0, vid->vm.size, PROT_READ|PROT_WRITE, MAP_SHARED, vid->fd, 0)) < 0){
491
        printf("error: mmap\n");
492
        free( vid );
493
        return 0;
494
    }
495
 
496
    /* setup for vmm */
497
    vid->vmm.frame  = 0;
498
    vid->vmm.width  = vid->width;
499
    vid->vmm.height = vid->height;
500
    vid->vmm.format= vid->palette;
501
 
502
    vid->video_cont_num = -1;
503
 
504
#ifdef USE_EYETOY
505
    JPEGToRGBInit(vid->width,vid->height);
506
#endif
507
    return vid;
508
}
509
 
510
int ar2VideoClose( AR2VideoParamT *vid )
511
{
512
    if(vid->video_cont_num >= 0){
513
        ar2VideoCapStop( vid );
514
    }
515
    close(vid->fd);
516
    if(vid->videoBuffer!=NULL)
517
        free(vid->videoBuffer);
518
    free( vid );
519
 
520
    return 0;
521
}
522
 
523
 
524
int ar2VideoCapStart( AR2VideoParamT *vid )
525
{
526
    if(vid->video_cont_num >= 0){
527
        printf("arVideoCapStart has already been called.\n");
528
        return -1;
529
    }
530
 
531
    vid->video_cont_num = 0;
532
    vid->vmm.frame      = vid->video_cont_num;
533
    if(ioctl(vid->fd, VIDIOCMCAPTURE, &vid->vmm) < 0) {
534
        return -1;
535
    }
536
    vid->vmm.frame = 1 - vid->vmm.frame;
537
    if( ioctl(vid->fd, VIDIOCMCAPTURE, &vid->vmm) < 0) {
538
        return -1;
539
    }
540
 
541
    return 0;
542
}
543
 
544
int ar2VideoCapNext( AR2VideoParamT *vid )
545
{
546
    if(vid->video_cont_num < 0){
547
        printf("arVideoCapStart has never been called.\n");
548
        return -1;
549
    }
550
 
551
    vid->vmm.frame = 1 - vid->vmm.frame;
552
    ioctl(vid->fd, VIDIOCMCAPTURE, &vid->vmm);
553
 
554
    return 0;
555
}
556
 
557
int ar2VideoCapStop( AR2VideoParamT *vid )
558
{
559
    if(vid->video_cont_num < 0){
560
        printf("arVideoCapStart has never been called.\n");
561
        return -1;
562
    }
563
    if(ioctl(vid->fd, VIDIOCSYNC, &vid->video_cont_num) < 0){
564
        printf("error: videosync\n");
565
        return -1;
566
    }
567
    vid->video_cont_num = -1;
568
 
569
    return 0;
570
}
571
 
572
 
573
ARUint8 *ar2VideoGetImage( AR2VideoParamT *vid )
574
{
575
    ARUint8 *buf;
576
 
577
    if(vid->video_cont_num < 0){
578
        printf("arVideoCapStart has never been called.\n");
579
        return NULL;
580
    }
581
 
582
    if(ioctl(vid->fd, VIDIOCSYNC, &vid->video_cont_num) < 0){
583
        printf("error: videosync\n");
584
        return NULL;
585
    }
586
    vid->video_cont_num = 1 - vid->video_cont_num;
587
 
588
    if(vid->video_cont_num == 0)
589
        buf=(vid->map + vid->vm.offsets[1]);
590
    else
591
        buf=(vid->map + vid->vm.offsets[0]);
592
 
593
    if(vid->palette == VIDEO_PALETTE_YUV420P)
594
    {
595
 
596
        ccvt_420p_bgr24(vid->width, vid->height, buf, buf+(vid->width*vid->height),
597
                        buf+(vid->width*vid->height)+(vid->width*vid->height)/4,
598
                        vid->videoBuffer);
599
        return vid->videoBuffer;
600
    }
601
#ifdef USE_EYETOY
602
        buf=JPEGToRGB(buf,vid->width, vid->height);
603
#endif
604
 
605
    return buf;
606
 
607
}
608
 
609
int ar2VideoInqSize(AR2VideoParamT *vid, int *x,int *y)
610
{
611
    *x = vid->vmm.width;
612
    *y = vid->vmm.height;
613
 
614
    return 0;
615
}