17
17
18
18
LOG_MODULE_REGISTER (uvc_sample , LOG_LEVEL_INF );
19
19
20
- const struct device * const uvc_dev = DEVICE_DT_GET (DT_NODELABEL (uvc ));
21
- const struct device * const video_dev = DEVICE_DT_GET (DT_CHOSEN (zephyr_camera ));
20
+ const static struct device * const uvc_dev = DEVICE_DT_GET (DT_NODELABEL (uvc ));
21
+ const static struct device * const video_dev = DEVICE_DT_GET (DT_CHOSEN (zephyr_camera ));
22
+
23
+ /* Format capabilities of video_dev, usd everywhere through the sampel */
24
+ static struct video_caps video_caps = {.type = VIDEO_BUF_TYPE_OUTPUT };
25
+
26
+ static size_t app_get_min_buf_size (const struct video_format * const fmt )
27
+ {
28
+ if (video_caps .min_line_count == LINE_COUNT_HEIGHT ) {
29
+ return fmt -> pitch * fmt -> height ;
30
+ } else {
31
+ return fmt -> pitch * video_caps .min_line_count ;
32
+ }
33
+ }
34
+
35
+ static void app_add_format (uint32_t pixfmt , uint16_t width , uint16_t height )
36
+ {
37
+ struct video_format fmt = {
38
+ .pixelformat = pixfmt ,
39
+ .width = width ,
40
+ .height = height ,
41
+ .type = VIDEO_BUF_TYPE_OUTPUT ,
42
+ };
43
+ int ret ;
44
+
45
+ /* Set the format to get the pitch */
46
+ ret = video_set_format (video_dev , & fmt );
47
+ if (ret != 0 ) {
48
+ LOG_ERR ("Could not set the format of %s" , video_dev -> name );
49
+ return ;
50
+ }
51
+
52
+ if (app_get_min_buf_size (& fmt ) > CONFIG_VIDEO_BUFFER_POOL_SZ_MAX ) {
53
+ LOG_WRN ("Skipping format %ux%u" , fmt .width , fmt .height );
54
+ return ;
55
+ }
56
+
57
+ uvc_add_format (uvc_dev , & fmt );
58
+ }
59
+
60
+ /* Submit to UVC only the formats expected to be working (enough memory for the size, etc.) */
61
+ static void app_add_filtered_formats (void )
62
+ {
63
+ for (int i = 0 ; video_caps .format_caps [i ].pixelformat != 0 ; i ++ ) {
64
+ const struct video_format_cap * vcap = & video_caps .format_caps [i ];
65
+
66
+ app_add_format (vcap -> pixelformat , vcap -> width_min , vcap -> height_min );
67
+
68
+ if (vcap -> width_min != vcap -> width_max || vcap -> height_min != vcap -> height_max ) {
69
+ app_add_format (vcap -> pixelformat , vcap -> width_max , vcap -> height_max );
70
+ }
71
+ }
72
+ }
22
73
23
74
int main (void )
24
75
{
25
76
struct usbd_context * sample_usbd ;
26
77
struct video_buffer * vbuf ;
27
78
struct video_format fmt = {0 };
28
- struct video_caps caps ;
79
+ struct video_frmival frmival = { 0 } ;
29
80
struct k_poll_signal sig ;
30
81
struct k_poll_event evt [1 ];
31
82
k_timeout_t timeout = K_FOREVER ;
@@ -37,16 +88,18 @@ int main(void)
37
88
return - ENODEV ;
38
89
}
39
90
40
- caps .type = VIDEO_BUF_TYPE_OUTPUT ;
41
-
42
- if (video_get_caps (video_dev , & caps )) {
91
+ ret = video_get_caps (video_dev , & video_caps );
92
+ if (ret != 0 ) {
43
93
LOG_ERR ("Unable to retrieve video capabilities" );
44
94
return 0 ;
45
95
}
46
96
47
- /* Must be done before initializing USB */
97
+ /* Must be called before usb_enable() */
48
98
uvc_set_video_dev (uvc_dev , video_dev );
49
99
100
+ /* Must be called before uvc_set_video_dev() */
101
+ app_add_filtered_formats ();
102
+
50
103
sample_usbd = sample_usbd_init_device (NULL );
51
104
if (sample_usbd == NULL ) {
52
105
return - ENODEV ;
@@ -59,7 +112,6 @@ int main(void)
59
112
60
113
LOG_INF ("Waiting the host to select the video format" );
61
114
62
- /* Get the video format once it is selected by the host */
63
115
while (true) {
64
116
fmt .type = VIDEO_BUF_TYPE_INPUT ;
65
117
@@ -75,17 +127,32 @@ int main(void)
75
127
k_sleep (K_MSEC (10 ));
76
128
}
77
129
78
- LOG_INF ("The host selected format '%s' %ux%u, preparing %u buffers of %u bytes" ,
130
+ ret = video_get_frmival (uvc_dev , & frmival );
131
+ if (ret != 0 ) {
132
+ LOG_ERR ("Failed to get the video frame interval" );
133
+ return ret ;
134
+ }
135
+
136
+ LOG_INF ("The host selected format '%s' %ux%u at frame interval %u/%u" ,
79
137
VIDEO_FOURCC_TO_STR (fmt .pixelformat ), fmt .width , fmt .height ,
80
- CONFIG_VIDEO_BUFFER_POOL_NUM_MAX , fmt . pitch * fmt . height );
138
+ frmival . numerator , frmival . denominator );
81
139
82
- /* Size to allocate for each buffer */
83
- if ( caps . min_line_count == LINE_COUNT_HEIGHT ) {
84
- bsize = fmt . pitch * fmt . height ;
85
- } else {
86
- bsize = fmt . pitch * caps . min_line_count ;
140
+ fmt . type = VIDEO_BUF_TYPE_OUTPUT ;
141
+
142
+ ret = video_set_format ( video_dev , & fmt ) ;
143
+ if ( ret != 0 ) {
144
+ LOG_WRN ( "Could not set the format of %s" , video_dev -> name ) ;
87
145
}
88
146
147
+ ret = video_set_frmival (video_dev , & frmival );
148
+ if (ret != 0 ) {
149
+ LOG_WRN ("Could not set the framerate of %s" , video_dev -> name );
150
+ }
151
+
152
+ bsize = app_get_min_buf_size (& fmt );
153
+
154
+ LOG_INF ("Preparing %u buffers of %u bytes" , CONFIG_VIDEO_BUFFER_POOL_NUM_MAX , bsize );
155
+
89
156
for (int i = 0 ; i < CONFIG_VIDEO_BUFFER_POOL_NUM_MAX ; i ++ ) {
90
157
vbuf = video_buffer_alloc (bsize , K_NO_WAIT );
91
158
if (vbuf == NULL ) {
0 commit comments