72
72
#include "tv.h"
73
73
#include "utils/color_out.h"
74
74
#include "utils/list.h"
75
+ #include "utils/macros.h"
75
76
#include "utils/misc.h" // ug_strerror
76
77
#include "v4l2_common.h"
77
78
#include "video.h"
@@ -492,15 +493,83 @@ static _Bool v4l2_cap_verify_params(_Bool permissive, const struct v4l2_format *
492
493
return 1 ;
493
494
}
494
495
496
+ struct parsed_opts {
497
+ uint32_t pixelformat ;
498
+ char * dev_name ;
499
+ uint32_t width ;
500
+ uint32_t height ;
501
+ uint32_t numerator ;
502
+ uint32_t denominator ;
503
+ int buffer_count ;
504
+ bool permissive ;
505
+ codec_t v4l2_convert_to ;
506
+ };
507
+
508
+ static bool
509
+ parse_fmt (char * fmt , struct parsed_opts * opts )
510
+ {
511
+ char * save_ptr = NULL ;
512
+ char * item = NULL ;;
513
+ while ((item = strtok_r (fmt , ":" , & save_ptr ))) {
514
+ fmt = NULL ;
515
+ if (strncmp (item , "dev=" , strlen ("dev=" )) == 0 ||
516
+ strncmp (item , "device=" , strlen ("device=" )) == 0 ) {
517
+ opts -> dev_name = strchr (item , '=' ) + 1 ;
518
+ } else if (strncmp (item , "fmt=" , strlen ("fmt=" )) == 0 ||
519
+ strncmp (item , "codec=" , strlen ("codec=" )) == 0 ) {
520
+ char * fmt = strchr (item , '=' ) + 1 ;
521
+ union {
522
+ uint32_t fourcc ;
523
+ char str [4 ];
524
+ } str_to_uint = { .fourcc = 0 };
525
+ memcpy (str_to_uint .str , fmt , MIN (strlen (fmt ), 4 ));
526
+ opts -> pixelformat = str_to_uint .fourcc ;
527
+ } else if (strncmp (item , "size=" , strlen ("size=" )) == 0 ) {
528
+ if (strchr (item , 'x' )) {
529
+ opts -> width = atoi (item + strlen ("size=" ));
530
+ opts -> height = atoi (strchr (item , 'x' ) + 1 );
531
+ }
532
+ } else if (strncmp (item , "tpf=" , strlen ("tpf=" )) == 0 ) {
533
+ opts -> numerator = atoi (item + strlen ("tpf=" ));
534
+ opts -> denominator = strchr (item , '/' ) == NULL
535
+ ? 1
536
+ : atoi (strchr (item , '/' ) + 1 );
537
+ } else if (strncmp (item , "fps=" , strlen ("fps=" )) == 0 ) {
538
+ opts -> denominator = atoi (item + strlen ("fps=" ));
539
+ opts -> numerator = strchr (item , '/' ) == NULL
540
+ ? 1
541
+ : atoi (strchr (item , '/' ) + 1 );
542
+ } else if (strncmp (item , "buffers=" , strlen ("buffers=" )) == 0 ) {
543
+ opts -> buffer_count = atoi (item + strlen ("buffers=" ));
544
+ assert (opts -> buffer_count <= MAX_BUF_COUNT );
545
+ } else if (strstr (item , "convert=" ) == item ) {
546
+ #ifdef HAVE_LIBV4LCONVERT
547
+ const char * codec = item + strlen ("convert=" );
548
+ opts -> v4l2_convert_to = get_codec_from_name (codec );
549
+ if (opts -> v4l2_convert_to == VIDEO_CODEC_NONE ) {
550
+ log_msg (LOG_LEVEL_ERROR ,
551
+ MOD_NAME "Unknown codec: %s\n" ,
552
+ codec );
553
+ return false;
554
+ }
555
+ #else
556
+ MSG (ERROR , "v4lconvert support not compiled in!" );
557
+ return false;
558
+ #endif
559
+ } else if (strstr (item , "permissive" ) == item ) {
560
+ opts -> permissive = 1 ;
561
+ } else {
562
+ MSG (ERROR , "Invalid configuration argument: %s\n" ,
563
+ item );
564
+ return false;
565
+ }
566
+ }
567
+ return true;
568
+ }
569
+
495
570
static int vidcap_v4l2_init (struct vidcap_params * params , void * * state )
496
571
{
497
- const char * dev_name = NULL ;
498
- uint32_t pixelformat = 0 ;
499
- uint32_t width = 0 ,
500
- height = 0 ;
501
- uint32_t numerator = 0 ,
502
- denominator = 0 ;
503
- codec_t v4l2_convert_to = VIDEO_CODEC_NONE ;
572
+ struct parsed_opts opts = { .buffer_count = DEFAULT_BUF_COUNT };
504
573
505
574
printf ("vidcap_v4l2_init\n" );
506
575
@@ -519,7 +588,6 @@ static int vidcap_v4l2_init(struct vidcap_params *params, void **state)
519
588
printf ("Unable to allocate v4l2 capture state\n" );
520
589
return VIDCAP_INIT_FAIL ;
521
590
}
522
- s -> buffer_count = DEFAULT_BUF_COUNT ;
523
591
s -> fd = -1 ;
524
592
s -> buffers_to_enqueue = simple_linked_list_init ();
525
593
pthread_mutex_init (& s -> lock , NULL );
@@ -530,82 +598,24 @@ static int vidcap_v4l2_init(struct vidcap_params *params, void **state)
530
598
if (vidcap_params_get_fmt (params )) {
531
599
tmp = strdup (vidcap_params_get_fmt (params ));
532
600
assert (tmp != NULL );
533
- char * init_fmt = tmp ;
534
- char * save_ptr = NULL ;
535
- char * item ;
536
- while ((item = strtok_r (init_fmt , ":" , & save_ptr ))) {
537
- if (strncmp (item , "dev=" , strlen ("dev=" )) == 0
538
- || strncmp (item , "device=" , strlen ("device=" )) == 0 ) {
539
- dev_name = strchr (item , '=' ) + 1 ;
540
- } else if (strncmp (item , "fmt=" , strlen ("fmt=" )) == 0
541
- || strncmp (item , "codec=" , strlen ("codec=" )) == 0 ) {
542
- char * fmt = strchr (item , '=' ) + 1 ;
543
- union {
544
- uint32_t fourcc ;
545
- char str [4 ];
546
- } str_to_uint ;
547
- int len = 4 ;
548
- if (strlen (fmt ) < 4 ) len = strlen (fmt );
549
- memset (str_to_uint .str , 0 , 4 );
550
- memcpy (str_to_uint .str , fmt , len );
551
- pixelformat = str_to_uint .fourcc ;
552
- } else if (strncmp (item , "size=" ,
553
- strlen ("size=" )) == 0 ) {
554
- if (strchr (item , 'x' )) {
555
- width = atoi (item + strlen ("size=" ));
556
- height = atoi (strchr (item , 'x' ) + 1 );
557
- }
558
- } else if (strncmp (item , "tpf=" , strlen ("tpf=" )) == 0 ) {
559
- numerator = atoi (item + strlen ("tpf=" ));
560
- if (strchr (item , '/' )) {
561
- denominator = atoi (strchr (item , '/' ) + 1 );
562
- } else {
563
- denominator = 1 ;
564
- }
565
- } else if (strncmp (item , "fps=" , strlen ("fps=" )) == 0 ) {
566
- denominator = atoi (item + strlen ("fps=" ));
567
- if (strchr (item , '/' )) {
568
- numerator = atoi (strchr (item , '/' ) + 1 );
569
- } else {
570
- numerator = 1 ;
571
- }
572
- } else if (strncmp (item , "buffers=" ,
573
- strlen ("buffers=" )) == 0 ) {
574
- s -> buffer_count = atoi (item + strlen ("buffers=" ));
575
- assert (s -> buffer_count <= MAX_BUF_COUNT );
576
- } else if (strstr (item , "convert=" ) == item ) {
577
- #ifdef HAVE_LIBV4LCONVERT
578
- const char * codec = item + strlen ("convert=" );
579
- v4l2_convert_to = get_codec_from_name (codec );
580
- if (v4l2_convert_to == VIDEO_CODEC_NONE ) {
581
- log_msg (LOG_LEVEL_ERROR , MOD_NAME "Unknown codec: %s\n" , codec );
582
- goto error ;
583
- }
584
- #else
585
- log_msg (LOG_LEVEL_ERROR , MOD_NAME "v4lconvert support not compiled in!" );
586
- goto error ;
587
- #endif
588
- } else if (strstr (item , "permissive" ) == item ) {
589
- s -> permissive = 1 ;
590
- } else {
591
- log_msg (LOG_LEVEL_ERROR , MOD_NAME "Invalid configuration argument: %s\n" ,
592
- item );
593
- goto error ;
594
- }
595
- init_fmt = NULL ;
601
+ if (!parse_fmt (tmp , & opts )) {
602
+ goto error ;
596
603
}
597
604
}
598
605
606
+ s -> buffer_count = opts .buffer_count ;
607
+ s -> permissive = opts .permissive ;
608
+
599
609
static_assert (V4L2_PROBE_MAX < 100 , "Pattern below has place only for 2 digits" );
600
610
char dev_name_try [] = "/dev/videoXX" ;
601
- if (dev_name != NULL ) {
602
- s -> fd = try_open_v4l2_device (LOG_LEVEL_ERROR , dev_name , V4L2_CAP_VIDEO_CAPTURE );
611
+ if (opts . dev_name != NULL ) {
612
+ s -> fd = try_open_v4l2_device (LOG_LEVEL_ERROR , opts . dev_name , V4L2_CAP_VIDEO_CAPTURE );
603
613
} else {
604
614
for (int i = 0 ; i < V4L2_PROBE_MAX ; ++ i ) {
605
615
snprintf (dev_name_try , sizeof dev_name_try , "/dev/video%d" , i );
606
616
s -> fd = try_open_v4l2_device (LOG_LEVEL_WARNING , dev_name_try , V4L2_CAP_VIDEO_CAPTURE );
607
617
if (s -> fd != -1 ) {
608
- dev_name = dev_name_try ;
618
+ opts . dev_name = dev_name_try ;
609
619
break ;
610
620
}
611
621
}
@@ -626,13 +636,13 @@ static int vidcap_v4l2_init(struct vidcap_params *params, void **state)
626
636
goto error ;
627
637
}
628
638
629
- if (pixelformat ) {
630
- fmt .fmt .pix .pixelformat = pixelformat ;
639
+ if (opts . pixelformat ) {
640
+ fmt .fmt .pix .pixelformat = opts . pixelformat ;
631
641
}
632
642
633
- if ( width != 0 && height != 0 ) {
634
- fmt .fmt .pix .width = width ;
635
- fmt .fmt .pix .height = height ;
643
+ if ( opts . width != 0 && opts . height != 0 ) {
644
+ fmt .fmt .pix .width = opts . width ;
645
+ fmt .fmt .pix .height = opts . height ;
636
646
}
637
647
638
648
fmt .fmt .pix .field = V4L2_FIELD_ANY ;
@@ -643,13 +653,17 @@ static int vidcap_v4l2_init(struct vidcap_params *params, void **state)
643
653
log_perror (LOG_LEVEL_ERROR , MOD_NAME "Unable to set video format" );
644
654
goto error ;
645
655
}
646
- if (numerator != 0 && denominator != 0 ) {
647
- stream_params .parm .capture .timeperframe .numerator = numerator ;
648
- stream_params .parm .capture .timeperframe .denominator = denominator ;
656
+ if (opts .numerator != 0 && opts .denominator != 0 ) {
657
+ stream_params .parm .capture .timeperframe .numerator =
658
+ opts .numerator ;
659
+ stream_params .parm .capture .timeperframe .denominator =
660
+ opts .denominator ;
649
661
}
650
662
struct v4l2_streamparm req_stream_params = stream_params ;
651
- if (numerator != 0 && denominator != 0 && ioctl (s -> fd , VIDIOC_S_PARM , & stream_params ) != 0 ) {
652
- log_perror (LOG_LEVEL_ERROR , MOD_NAME "Unable to set stream params" );
663
+ if (opts .numerator != 0 && opts .denominator != 0 &&
664
+ ioctl (s -> fd , VIDIOC_S_PARM , & stream_params ) != 0 ) {
665
+ log_perror (LOG_LEVEL_ERROR ,
666
+ MOD_NAME "Unable to set stream params" );
653
667
goto error ;
654
668
}
655
669
if (!v4l2_cap_verify_params (s -> permissive , & req_fmt , & fmt , & req_stream_params , & stream_params ) && !s -> permissive ) {
@@ -673,28 +687,34 @@ static int vidcap_v4l2_init(struct vidcap_params *params, void **state)
673
687
674
688
s -> desc .tile_count = 1 ;
675
689
676
- if (v4l2_convert_to == VIDEO_CODEC_NONE ) {
690
+ if (opts . v4l2_convert_to == VC_NONE ) {
677
691
s -> desc .color_spec = get_v4l2_to_ug (fmt .fmt .pix .pixelformat );
678
692
if (s -> desc .color_spec == VIDEO_CODEC_NONE ) {
679
693
char fcc [5 ];
680
694
memcpy (fcc , & fmt .fmt .pix .pixelformat , 4 );
681
695
fcc [4 ] = '\0' ;
682
696
log_msg (LOG_LEVEL_WARNING , MOD_NAME "No mapping for FCC '%s', converting to RGB!\n" , fcc );
683
- v4l2_convert_to = s -> dst_fmt .fmt .pix .pixelformat = V4L2_PIX_FMT_RGB24 ;
697
+ opts .v4l2_convert_to = s -> dst_fmt .fmt .pix .pixelformat =
698
+ V4L2_PIX_FMT_RGB24 ;
684
699
}
685
700
}
686
- if (v4l2_convert_to != VIDEO_CODEC_NONE ) {
701
+ if (opts . v4l2_convert_to != VC_NONE ) {
687
702
#ifdef HAVE_LIBV4LCONVERT
688
- s -> dst_fmt .fmt .pix .pixelformat = get_ug_to_v4l2 (v4l2_convert_to );
703
+ s -> dst_fmt .fmt .pix .pixelformat =
704
+ get_ug_to_v4l2 (opts .v4l2_convert_to );
689
705
if (!v4lconvert_supported_dst_format (s -> dst_fmt .fmt .pix .pixelformat )) {
690
- log_msg (LOG_LEVEL_WARNING , MOD_NAME "Conversion to %s doesn't seem to be supported by v4lconvert but proceeding as requested...\n" , get_codec_name (v4l2_convert_to ));
706
+ MSG (WARNING ,
707
+ "Conversion to %s doesn't seem to be supported by "
708
+ "v4lconvert but proceeding as requested...\n" ,
709
+ get_codec_name (opts .v4l2_convert_to ));
691
710
}
692
711
693
712
if (s -> dst_fmt .fmt .pix .pixelformat == 0 ) {
694
- log_msg (LOG_LEVEL_ERROR , MOD_NAME "Cannot find %s to V4L2 mapping!\n" , get_codec_name (v4l2_convert_to ));
713
+ MSG (ERROR , "Cannot find %s to V4L2 mapping!\n" ,
714
+ get_codec_name (opts .v4l2_convert_to ));
695
715
goto error ;
696
716
}
697
- s -> desc .color_spec = v4l2_convert_to ;
717
+ s -> desc .color_spec = opts . v4l2_convert_to ;
698
718
#endif
699
719
}
700
720
@@ -716,7 +736,7 @@ static int vidcap_v4l2_init(struct vidcap_params *params, void **state)
716
736
717
737
#ifdef HAVE_LIBV4LCONVERT
718
738
s -> convert = NULL ;
719
- if (v4l2_convert_to != VIDEO_CODEC_NONE ) {
739
+ if (opts . v4l2_convert_to != VC_NONE ) {
720
740
s -> convert = v4lconvert_create (s -> fd );
721
741
}
722
742
#endif
@@ -746,7 +766,7 @@ static int vidcap_v4l2_init(struct vidcap_params *params, void **state)
746
766
MSG (NOTICE , "Capturing %dx%d @%.2f%s %s from %s\n" , s -> desc .width ,
747
767
s -> desc .height , s -> desc .fps ,
748
768
get_interlacing_suffix (s -> desc .interlacing ),
749
- get_codec_name (s -> desc .color_spec ), dev_name );
769
+ get_codec_name (s -> desc .color_spec ), opts . dev_name );
750
770
751
771
* state = s ;
752
772
return VIDCAP_INIT_OK ;
0 commit comments