Skip to content

Commit be72545

Browse files
committed
samples: video: tcpserversink: sync with capture sample
Sync with video capture sample. Signed-off-by: Hugues Fruchet <[email protected]>
1 parent 3a6cfe3 commit be72545

File tree

2 files changed

+213
-2
lines changed

2 files changed

+213
-2
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
mainmenu "TCP camera streaming sample application"
5+
6+
menu "Video capture configuration"
7+
8+
config VIDEO_SOURCE_CROP_LEFT
9+
int "Crop area left value"
10+
default 0
11+
help
12+
Left value of the crop area within the video source.
13+
14+
config VIDEO_SOURCE_CROP_TOP
15+
int "Crop area top value"
16+
default 0
17+
help
18+
Top value of the crop area within the video source.
19+
20+
config VIDEO_SOURCE_CROP_WIDTH
21+
int "Crop area width value"
22+
default 0
23+
help
24+
Width value of the crop area within the video source.
25+
If set to 0, the crop is not applied.
26+
27+
config VIDEO_SOURCE_CROP_HEIGHT
28+
int "Crop area height value"
29+
default 0
30+
help
31+
Height value of the crop area within the video source.
32+
If set to 0, the crop is not applied.
33+
34+
config VIDEO_FRAME_HEIGHT
35+
int "Height of the video frame"
36+
default 0
37+
help
38+
Height of the video frame. If set to 0, the default height is used.
39+
40+
config VIDEO_FRAME_WIDTH
41+
int "Width of the video frame"
42+
default 0
43+
help
44+
Width of the video frame. If set to 0, the default width is used.
45+
46+
config VIDEO_PIXEL_FORMAT
47+
string "Pixel format of the video frame"
48+
help
49+
Pixel format of the video frame. If not set, the default pixel format is used.
50+
51+
config VIDEO_CTRL_HFLIP
52+
bool "Mirror the video frame horizontally"
53+
help
54+
If set, mirror the video frame horizontally
55+
56+
config VIDEO_CTRL_VFLIP
57+
bool "Mirror the video frame vertically"
58+
help
59+
If set, mirror the video frame vertically
60+
61+
endmenu
62+
63+
source "Kconfig.zephyr"

samples/drivers/video/tcpserversink/src/main.c

Lines changed: 150 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <zephyr/device.h>
88
#include <zephyr/drivers/video.h>
9+
#include <zephyr/drivers/video-controls.h>
910
#include <zephyr/kernel.h>
1011
#include <zephyr/logging/log.h>
1112
#include <zephyr/net/socket.h>
@@ -36,11 +37,22 @@ int main(void)
3637
socklen_t client_addr_len = sizeof(client_addr);
3738
struct video_buffer *buffers[2];
3839
struct video_buffer *vbuf = &(struct video_buffer){};
39-
int i, ret, sock, client;
40+
int ret, sock, client;
4041
struct video_format fmt;
4142
struct video_caps caps;
43+
struct video_frmival frmival;
44+
struct video_frmival_enum fie;
4245
enum video_buf_type type = VIDEO_BUF_TYPE_OUTPUT;
4346
const struct device *video_dev;
47+
#if (CONFIG_VIDEO_SOURCE_CROP_WIDTH && CONFIG_VIDEO_SOURCE_CROP_HEIGHT) || \
48+
CONFIG_VIDEO_FRAME_HEIGHT || CONFIG_VIDEO_FRAME_WIDTH
49+
struct video_selection sel = {
50+
.type = VIDEO_BUF_TYPE_OUTPUT,
51+
};
52+
#endif
53+
size_t bsize;
54+
int i = 0;
55+
int err;
4456

4557
video_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera));
4658
if (!device_is_ready(video_dev)) {
@@ -80,6 +92,17 @@ int main(void)
8092
return 0;
8193
}
8294

95+
LOG_INF("- Capabilities:");
96+
while (caps.format_caps[i].pixelformat) {
97+
const struct video_format_cap *fcap = &caps.format_caps[i];
98+
/* fourcc to string */
99+
LOG_INF(" %s width [%u; %u; %u] height [%u; %u; %u]",
100+
VIDEO_FOURCC_TO_STR(fcap->pixelformat),
101+
fcap->width_min, fcap->width_max, fcap->width_step,
102+
fcap->height_min, fcap->height_max, fcap->height_step);
103+
i++;
104+
}
105+
83106
/* Get default/native format */
84107
fmt.type = type;
85108
if (video_get_format(video_dev, &fmt)) {
@@ -95,9 +118,134 @@ int main(void)
95118
return 0;
96119
}
97120

121+
/* Set the crop setting if necessary */
122+
#if CONFIG_VIDEO_SOURCE_CROP_WIDTH && CONFIG_VIDEO_SOURCE_CROP_HEIGHT
123+
sel.target = VIDEO_SEL_TGT_CROP;
124+
sel.rect.left = CONFIG_VIDEO_SOURCE_CROP_LEFT;
125+
sel.rect.top = CONFIG_VIDEO_SOURCE_CROP_TOP;
126+
sel.rect.width = CONFIG_VIDEO_SOURCE_CROP_WIDTH;
127+
sel.rect.height = CONFIG_VIDEO_SOURCE_CROP_HEIGHT;
128+
if (video_set_selection(video_dev, &sel)) {
129+
LOG_ERR("Unable to set selection crop");
130+
return 0;
131+
}
132+
LOG_INF("Selection crop set to (%u,%u)/%ux%u",
133+
sel.rect.left, sel.rect.top, sel.rect.width, sel.rect.height);
134+
#endif
135+
136+
#if CONFIG_VIDEO_FRAME_HEIGHT || CONFIG_VIDEO_FRAME_WIDTH
137+
#if CONFIG_VIDEO_FRAME_HEIGHT
138+
fmt.height = CONFIG_VIDEO_FRAME_HEIGHT;
139+
#endif
140+
141+
#if CONFIG_VIDEO_FRAME_WIDTH
142+
fmt.width = CONFIG_VIDEO_FRAME_WIDTH;
143+
#endif
144+
145+
/*
146+
* Check (if possible) if targeted size is same as crop
147+
* and if compose is necessary
148+
*/
149+
sel.target = VIDEO_SEL_TGT_CROP;
150+
err = video_get_selection(video_dev, &sel);
151+
if (err < 0 && err != -ENOSYS) {
152+
LOG_ERR("Unable to get selection crop");
153+
return 0;
154+
}
155+
156+
if (err == 0 && (sel.rect.width != fmt.width || sel.rect.height != fmt.height)) {
157+
sel.target = VIDEO_SEL_TGT_COMPOSE;
158+
sel.rect.left = 0;
159+
sel.rect.top = 0;
160+
sel.rect.width = fmt.width;
161+
sel.rect.height = fmt.height;
162+
err = video_set_selection(video_dev, &sel);
163+
if (err < 0 && err != -ENOSYS) {
164+
LOG_ERR("Unable to set selection compose");
165+
return 0;
166+
}
167+
}
168+
#endif
169+
170+
if (strcmp(CONFIG_VIDEO_PIXEL_FORMAT, "")) {
171+
fmt.pixelformat = VIDEO_FOURCC_FROM_STR(CONFIG_VIDEO_PIXEL_FORMAT);
172+
}
173+
174+
LOG_INF("- Video format: %s %ux%u",
175+
VIDEO_FOURCC_TO_STR(fmt.pixelformat), fmt.width, fmt.height);
176+
177+
if (video_set_format(video_dev, &fmt)) {
178+
LOG_ERR("Unable to set format");
179+
return 0;
180+
}
181+
182+
if (!video_get_frmival(video_dev, &frmival)) {
183+
LOG_INF("- Default frame rate : %f fps",
184+
1.0 * frmival.denominator / frmival.numerator);
185+
}
186+
187+
LOG_INF("- Supported frame intervals for the default format:");
188+
memset(&fie, 0, sizeof(fie));
189+
fie.format = &fmt;
190+
while (video_enum_frmival(video_dev, &fie) == 0) {
191+
if (fie.type == VIDEO_FRMIVAL_TYPE_DISCRETE) {
192+
LOG_INF(" %u/%u", fie.discrete.numerator, fie.discrete.denominator);
193+
} else {
194+
LOG_INF(" [min = %u/%u; max = %u/%u; step = %u/%u]",
195+
fie.stepwise.min.numerator, fie.stepwise.min.denominator,
196+
fie.stepwise.max.numerator, fie.stepwise.max.denominator,
197+
fie.stepwise.step.numerator, fie.stepwise.step.denominator);
198+
}
199+
fie.index++;
200+
}
201+
202+
/* Get supported controls */
203+
LOG_INF("- Supported controls:");
204+
const struct device *last_dev = NULL;
205+
struct video_ctrl_query cq = {.dev = video_dev, .id = VIDEO_CTRL_FLAG_NEXT_CTRL};
206+
207+
while (!video_query_ctrl(&cq)) {
208+
if (cq.dev != last_dev) {
209+
last_dev = cq.dev;
210+
LOG_INF("\t\tdevice: %s", cq.dev->name);
211+
}
212+
video_print_ctrl(&cq);
213+
cq.id |= VIDEO_CTRL_FLAG_NEXT_CTRL;
214+
}
215+
216+
/* Set controls */
217+
struct video_control ctrl = {.id = VIDEO_CID_HFLIP, .val = 1};
218+
int tp_set_ret = -ENOTSUP;
219+
220+
if (IS_ENABLED(CONFIG_VIDEO_CTRL_HFLIP)) {
221+
video_set_ctrl(video_dev, &ctrl);
222+
}
223+
224+
if (IS_ENABLED(CONFIG_VIDEO_CTRL_VFLIP)) {
225+
ctrl.id = VIDEO_CID_VFLIP;
226+
video_set_ctrl(video_dev, &ctrl);
227+
}
228+
229+
if (IS_ENABLED(CONFIG_TEST)) {
230+
ctrl.id = VIDEO_CID_TEST_PATTERN;
231+
tp_set_ret = video_set_ctrl(video_dev, &ctrl);
232+
}
233+
234+
/* Size to allocate for each buffer */
235+
if (caps.min_line_count == LINE_COUNT_HEIGHT) {
236+
bsize = fmt.pitch * fmt.height;
237+
} else {
238+
bsize = fmt.pitch * caps.min_line_count;
239+
}
240+
98241
/* Alloc Buffers */
99242
for (i = 0; i < ARRAY_SIZE(buffers); i++) {
100-
buffers[i] = video_buffer_alloc(fmt.pitch * fmt.height, K_FOREVER);
243+
/*
244+
* For some hardwares, such as the PxP used on i.MX RT1170 to do image rotation,
245+
* buffer alignment is needed in order to achieve the best performance
246+
*/
247+
buffers[i] = video_buffer_aligned_alloc(bsize, CONFIG_VIDEO_BUFFER_POOL_ALIGN,
248+
K_FOREVER);
101249
if (buffers[i] == NULL) {
102250
LOG_ERR("Unable to alloc video buffer");
103251
return 0;

0 commit comments

Comments
 (0)