1717
1818LOG_MODULE_REGISTER (uvc_sample , LOG_LEVEL_INF );
1919
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, used everywhere through the sample */
24+ static struct video_caps video_caps = {.type = VIDEO_BUF_TYPE_OUTPUT };
25+
26+ static void app_add_format (uint32_t pixfmt , uint32_t width , uint32_t height )
27+ {
28+ struct video_format fmt = {
29+ .pixelformat = pixfmt ,
30+ .width = width ,
31+ .height = height ,
32+ .type = VIDEO_BUF_TYPE_OUTPUT ,
33+ };
34+ int ret ;
35+
36+ /* Set the format to get the size */
37+ ret = video_set_format (video_dev , & fmt );
38+ if (ret != 0 ) {
39+ LOG_ERR ("Could not set the format of %s to %s %ux%u (size %u)" ,
40+ video_dev -> name , VIDEO_FOURCC_TO_STR (fmt .pixelformat ),
41+ fmt .width , fmt .height , fmt .size );
42+ return ;
43+ }
44+
45+ if (fmt .size > CONFIG_VIDEO_BUFFER_POOL_SZ_MAX ) {
46+ LOG_WRN ("Skipping format %ux%u" , fmt .width , fmt .height );
47+ return ;
48+ }
49+
50+ uvc_add_format (uvc_dev , & fmt );
51+ }
52+
53+ /* Submit to UVC only the formats expected to be working (enough memory for the size, etc.) */
54+ static void app_add_filtered_formats (void )
55+ {
56+ for (int i = 0 ; video_caps .format_caps [i ].pixelformat != 0 ; i ++ ) {
57+ const struct video_format_cap * vcap = & video_caps .format_caps [i ];
58+
59+ app_add_format (vcap -> pixelformat , vcap -> width_min , vcap -> height_min );
60+
61+ if (vcap -> width_min != vcap -> width_max || vcap -> height_min != vcap -> height_max ) {
62+ app_add_format (vcap -> pixelformat , vcap -> width_max , vcap -> height_max );
63+ }
64+ }
65+ }
2266
2367int main (void )
2468{
2569 struct usbd_context * sample_usbd ;
2670 struct video_buffer * vbuf ;
2771 struct video_format fmt = {0 };
28- struct video_caps caps ;
72+ struct video_frmival frmival = { 0 } ;
2973 struct k_poll_signal sig ;
3074 struct k_poll_event evt [1 ];
3175 k_timeout_t timeout = K_FOREVER ;
@@ -36,16 +80,18 @@ int main(void)
3680 return - ENODEV ;
3781 }
3882
39- caps .type = VIDEO_BUF_TYPE_OUTPUT ;
40-
41- if (video_get_caps (video_dev , & caps )) {
83+ ret = video_get_caps (video_dev , & video_caps );
84+ if (ret != 0 ) {
4285 LOG_ERR ("Unable to retrieve video capabilities" );
4386 return 0 ;
4487 }
4588
46- /* Must be done before initializing USB */
89+ /* Must be called before usb_enable() */
4790 uvc_set_video_dev (uvc_dev , video_dev );
4891
92+ /* Must be called before usb_enable() */
93+ app_add_filtered_formats ();
94+
4995 sample_usbd = sample_usbd_init_device (NULL );
5096 if (sample_usbd == NULL ) {
5197 return - ENODEV ;
@@ -58,7 +104,6 @@ int main(void)
58104
59105 LOG_INF ("Waiting the host to select the video format" );
60106
61- /* Get the video format once it is selected by the host */
62107 while (true) {
63108 fmt .type = VIDEO_BUF_TYPE_INPUT ;
64109
@@ -74,9 +119,31 @@ int main(void)
74119 k_sleep (K_MSEC (10 ));
75120 }
76121
77- LOG_INF ("The host selected format '%s' %ux%u, preparing %u buffers of %u bytes" ,
122+ ret = video_get_frmival (uvc_dev , & frmival );
123+ if (ret != 0 ) {
124+ LOG_ERR ("Failed to get the video frame interval" );
125+ return ret ;
126+ }
127+
128+ LOG_INF ("The host selected format '%s' %ux%u at frame interval %u/%u" ,
78129 VIDEO_FOURCC_TO_STR (fmt .pixelformat ), fmt .width , fmt .height ,
79- CONFIG_VIDEO_BUFFER_POOL_NUM_MAX , fmt .pitch * fmt .height );
130+ frmival .numerator , frmival .denominator );
131+
132+ fmt .type = VIDEO_BUF_TYPE_OUTPUT ;
133+
134+ ret = video_set_format (video_dev , & fmt );
135+ if (ret != 0 ) {
136+ LOG_ERR ("Could not set the format of %s to %s %ux%u (size %u)" ,
137+ video_dev -> name , VIDEO_FOURCC_TO_STR (fmt .pixelformat ),
138+ fmt .width , fmt .height , fmt .size );
139+ }
140+
141+ ret = video_set_frmival (video_dev , & frmival );
142+ if (ret != 0 ) {
143+ LOG_WRN ("Could not set the framerate of %s" , video_dev -> name );
144+ }
145+
146+ LOG_INF ("Preparing %u buffers of %u bytes" , CONFIG_VIDEO_BUFFER_POOL_NUM_MAX , fmt .size );
80147
81148 for (int i = 0 ; i < CONFIG_VIDEO_BUFFER_POOL_NUM_MAX ; i ++ ) {
82149 vbuf = video_buffer_alloc (fmt .size , K_NO_WAIT );
0 commit comments