-
Couldn't load subscription status.
- Fork 8.1k
Allow STM32 DCMIPP to work with UVC sample #94562
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
dfe5139
ee17acf
49458fc
fe96014
a5971e1
d2e3f66
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1331,22 +1331,94 @@ static int stm32_dcmipp_dequeue(const struct device *dev, struct video_buffer ** | |
| } | ||
|
|
||
| /* | ||
| * TODO: caps aren't yet handled hence give back straight the caps given by the | ||
| * source. Normally this should be the intersection of what the source produces | ||
| * vs what the DCMIPP can input (for pipe0) and, for pipe 1 and 2, for a given | ||
| * input format, generate caps based on capabilities, color conversion, decimation | ||
| * etc | ||
| * For MAIN / AUX pipe, it is necessary that the pitch is a multiple of 16 bytes. | ||
| * Give here the multiple in number of pixels, which depends on the format chosen | ||
| */ | ||
| #define DCMIPP_CEIL_DIV_ROUND_UP_MUL(val, div, mul) \ | ||
| ((((val) + (div) - 1) / (div) + (mul) - 1) / (mul) * (mul)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: should we add a new line after each |
||
|
|
||
| #define DCMIPP_CEIL_DIV(val, div) \ | ||
| (((val) + (div) - 1) / (div)) | ||
|
|
||
| #define DCMIPP_VIDEO_FORMAT_CAP(format, pixmul) { \ | ||
| .pixelformat = VIDEO_PIX_FMT_##format, \ | ||
| .width_min = DCMIPP_CEIL_DIV_ROUND_UP_MUL(CONFIG_VIDEO_STM32_DCMIPP_SENSOR_WIDTH, \ | ||
| STM32_DCMIPP_MAX_PIPE_SCALE_FACTOR, \ | ||
| pixmul), \ | ||
| .width_max = CONFIG_VIDEO_STM32_DCMIPP_SENSOR_WIDTH / (pixmul) * (pixmul), \ | ||
| .height_min = DCMIPP_CEIL_DIV(CONFIG_VIDEO_STM32_DCMIPP_SENSOR_HEIGHT, \ | ||
| STM32_DCMIPP_MAX_PIPE_SCALE_FACTOR), \ | ||
| .height_max = CONFIG_VIDEO_STM32_DCMIPP_SENSOR_HEIGHT, \ | ||
| .width_step = pixmul, .height_step = 1, \ | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This closing brace should be indented by a tab IMHO, since it's part of a macro. |
||
|
|
||
| static const struct video_format_cap stm32_dcmipp_dump_fmt[] = { | ||
| { | ||
| .pixelformat = VIDEO_FOURCC_FROM_STR(CONFIG_VIDEO_STM32_DCMIPP_SENSOR_PIXEL_FORMAT), | ||
| .width_min = CONFIG_VIDEO_STM32_DCMIPP_SENSOR_WIDTH, | ||
| .width_max = CONFIG_VIDEO_STM32_DCMIPP_SENSOR_WIDTH, | ||
| .height_min = CONFIG_VIDEO_STM32_DCMIPP_SENSOR_HEIGHT, | ||
| .height_max = CONFIG_VIDEO_STM32_DCMIPP_SENSOR_HEIGHT, | ||
| .width_step = 1, .height_step = 1, | ||
| }, | ||
| {0}, | ||
| }; | ||
|
|
||
| static const struct video_format_cap stm32_dcmipp_main_fmts[] = { | ||
| DCMIPP_VIDEO_FORMAT_CAP(RGB565, 8), | ||
| DCMIPP_VIDEO_FORMAT_CAP(YUYV, 8), | ||
| DCMIPP_VIDEO_FORMAT_CAP(YVYU, 8), | ||
| DCMIPP_VIDEO_FORMAT_CAP(GREY, 16), | ||
| DCMIPP_VIDEO_FORMAT_CAP(RGB24, 16), | ||
| DCMIPP_VIDEO_FORMAT_CAP(BGR24, 16), | ||
| DCMIPP_VIDEO_FORMAT_CAP(ARGB32, 4), | ||
| DCMIPP_VIDEO_FORMAT_CAP(ABGR32, 4), | ||
| DCMIPP_VIDEO_FORMAT_CAP(RGBA32, 4), | ||
| DCMIPP_VIDEO_FORMAT_CAP(BGRA32, 4), | ||
| DCMIPP_VIDEO_FORMAT_CAP(NV12, 16), | ||
| DCMIPP_VIDEO_FORMAT_CAP(NV21, 16), | ||
| DCMIPP_VIDEO_FORMAT_CAP(NV16, 16), | ||
| DCMIPP_VIDEO_FORMAT_CAP(NV61, 16), | ||
| DCMIPP_VIDEO_FORMAT_CAP(YUV420, 16), | ||
| DCMIPP_VIDEO_FORMAT_CAP(YVU420, 16), | ||
| {0}, | ||
| }; | ||
|
Comment on lines
+1367
to
+1385
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to me quite error prone. We would be mixing up static const struct video_format_cap table of structure for the aux and table of pointers for the main. Moreover if for some reason we add / delete on aux then we need to ensure it is ok as well on the main. So I feel like it is better to stick to this version which might indeed consume a bit more code space. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can all be optimized as soon as there is a |
||
|
|
||
| static const struct video_format_cap stm32_dcmipp_aux_fmts[] = { | ||
| DCMIPP_VIDEO_FORMAT_CAP(RGB565, 8), | ||
| DCMIPP_VIDEO_FORMAT_CAP(YUYV, 8), | ||
| DCMIPP_VIDEO_FORMAT_CAP(YVYU, 8), | ||
| DCMIPP_VIDEO_FORMAT_CAP(GREY, 16), | ||
| DCMIPP_VIDEO_FORMAT_CAP(RGB24, 16), | ||
| DCMIPP_VIDEO_FORMAT_CAP(BGR24, 16), | ||
| DCMIPP_VIDEO_FORMAT_CAP(ARGB32, 4), | ||
| DCMIPP_VIDEO_FORMAT_CAP(ABGR32, 4), | ||
| DCMIPP_VIDEO_FORMAT_CAP(RGBA32, 4), | ||
| DCMIPP_VIDEO_FORMAT_CAP(BGRA32, 4), | ||
| {0}, | ||
| }; | ||
|
|
||
| static int stm32_dcmipp_get_caps(const struct device *dev, struct video_caps *caps) | ||
| { | ||
| const struct stm32_dcmipp_config *config = dev->config; | ||
| int ret; | ||
| struct stm32_dcmipp_pipe_data *pipe = dev->data; | ||
|
|
||
| ret = video_get_caps(config->source_dev, caps); | ||
| switch (pipe->id) { | ||
| case DCMIPP_PIPE0: | ||
| caps->format_caps = stm32_dcmipp_dump_fmt; | ||
| break; | ||
| case DCMIPP_PIPE1: | ||
| caps->format_caps = stm32_dcmipp_main_fmts; | ||
| break; | ||
| case DCMIPP_PIPE2: | ||
| caps->format_caps = stm32_dcmipp_aux_fmts; | ||
| break; | ||
| default: | ||
| CODE_UNREACHABLE; | ||
| } | ||
|
|
||
| caps->min_vbuf_count = 1; | ||
|
|
||
| return ret; | ||
| return 0; | ||
| } | ||
|
|
||
| static int stm32_dcmipp_get_frmival(const struct device *dev, struct video_frmival *frmival) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -98,10 +98,14 @@ int main(void) | |
| struct video_frmival frmival; | ||
| struct video_frmival_enum fie; | ||
| enum video_buf_type type = VIDEO_BUF_TYPE_OUTPUT; | ||
| #if (CONFIG_VIDEO_SOURCE_CROP_WIDTH && CONFIG_VIDEO_SOURCE_CROP_HEIGHT) || \ | ||
| CONFIG_VIDEO_FRAME_HEIGHT || CONFIG_VIDEO_FRAME_WIDTH | ||
| struct video_selection sel = { | ||
| #if (CONFIG_VIDEO_SOURCE_CROP_WIDTH && CONFIG_VIDEO_SOURCE_CROP_HEIGHT) | ||
| struct video_selection crop_sel = { | ||
| .type = VIDEO_BUF_TYPE_OUTPUT, | ||
| .target = VIDEO_SEL_TGT_CROP; | ||
| .rect.left = CONFIG_VIDEO_SOURCE_CROP_LEFT; | ||
| .rect.top = CONFIG_VIDEO_SOURCE_CROP_TOP; | ||
| .rect.width = CONFIG_VIDEO_SOURCE_CROP_WIDTH; | ||
| .rect.height = CONFIG_VIDEO_SOURCE_CROP_HEIGHT; | ||
| }; | ||
| #endif | ||
| unsigned int frame = 0; | ||
|
|
@@ -149,20 +153,14 @@ int main(void) | |
|
|
||
| /* Set the crop setting if necessary */ | ||
| #if CONFIG_VIDEO_SOURCE_CROP_WIDTH && CONFIG_VIDEO_SOURCE_CROP_HEIGHT | ||
| sel.target = VIDEO_SEL_TGT_CROP; | ||
| sel.rect.left = CONFIG_VIDEO_SOURCE_CROP_LEFT; | ||
| sel.rect.top = CONFIG_VIDEO_SOURCE_CROP_TOP; | ||
| sel.rect.width = CONFIG_VIDEO_SOURCE_CROP_WIDTH; | ||
| sel.rect.height = CONFIG_VIDEO_SOURCE_CROP_HEIGHT; | ||
| if (video_set_selection(video_dev, &sel)) { | ||
| if (video_set_selection(video_dev, &crop_sel)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer if (video_set_selection(video_dev, &crop_sel) < 0) {There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is nonsense, even would introduce undefined behavior and -1 from my side. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you mean by an undefined behavior? if (video_set_selection(video_dev, &crop_sel) != 0) {I'm fine too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is completely different proposal, at least for USB that would be preferable, but there is no difference between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My mistake. I misised we're here in a demo sample. |
||
| LOG_ERR("Unable to set selection crop"); | ||
| return 0; | ||
| } | ||
| LOG_INF("Selection crop set to (%u,%u)/%ux%u", | ||
| sel.rect.left, sel.rect.top, sel.rect.width, sel.rect.height); | ||
| #endif | ||
|
|
||
| #if CONFIG_VIDEO_FRAME_HEIGHT || CONFIG_VIDEO_FRAME_WIDTH | ||
| #if CONFIG_VIDEO_FRAME_HEIGHT | ||
| fmt.height = CONFIG_VIDEO_FRAME_HEIGHT; | ||
| #endif | ||
|
|
@@ -171,39 +169,14 @@ int main(void) | |
| fmt.width = CONFIG_VIDEO_FRAME_WIDTH; | ||
| #endif | ||
|
|
||
| /* | ||
| * Check (if possible) if targeted size is same as crop | ||
| * and if compose is necessary | ||
| */ | ||
| sel.target = VIDEO_SEL_TGT_CROP; | ||
| err = video_get_selection(video_dev, &sel); | ||
| if (err < 0 && err != -ENOSYS) { | ||
| LOG_ERR("Unable to get selection crop"); | ||
| return 0; | ||
| } | ||
|
|
||
| if (err == 0 && (sel.rect.width != fmt.width || sel.rect.height != fmt.height)) { | ||
| sel.target = VIDEO_SEL_TGT_COMPOSE; | ||
| sel.rect.left = 0; | ||
| sel.rect.top = 0; | ||
| sel.rect.width = fmt.width; | ||
| sel.rect.height = fmt.height; | ||
| err = video_set_selection(video_dev, &sel); | ||
| if (err < 0 && err != -ENOSYS) { | ||
| LOG_ERR("Unable to set selection compose"); | ||
| return 0; | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
| if (strcmp(CONFIG_VIDEO_PIXEL_FORMAT, "")) { | ||
| fmt.pixelformat = VIDEO_FOURCC_FROM_STR(CONFIG_VIDEO_PIXEL_FORMAT); | ||
| } | ||
|
|
||
| LOG_INF("- Video format: %s %ux%u", | ||
| VIDEO_FOURCC_TO_STR(fmt.pixelformat), fmt.width, fmt.height); | ||
|
|
||
| if (video_set_format(video_dev, &fmt)) { | ||
| if (video_set_compose_format(video_dev, &fmt)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto: if (video_set_compose_format(video_dev, &fmt) < 0) {There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as #94562 (comment) |
||
| LOG_ERR("Unable to set format"); | ||
| return 0; | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.