-
Notifications
You must be signed in to change notification settings - Fork 8.1k
video: selection api (crop/compose) addition (api/shell/sample) + dcmipp implementation #91878
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
video: selection api (crop/compose) addition (api/shell/sample) + dcmipp implementation #91878
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Adds support for crop and compose selection in the video subsystem, with sample, shell, and DCMIPP driver updates.
- Introduce
video_selection
API invideo.h
for crop/compose control - Extend the capture sample and Kconfig to configure source crop and compose
- Implement selection handling in the shell and STM32 DCMIPP driver
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
Show a summary per file
File | Description |
---|---|
samples/drivers/video/capture/src/main.c | Apply optional crop and compose settings in sample |
samples/drivers/video/capture/Kconfig | Add VIDEO_SOURCE_CROP_* configuration options |
include/zephyr/drivers/video.h | Define video_selection structs and APIs |
drivers/video/video_stm32_dcmipp.c | Implement crop/compose logic and API callbacks |
drivers/video/video_shell.c | Add shell commands and parsing for selection |
Comments suppressed due to low confidence (2)
drivers/video/video_stm32_dcmipp.c:647
- [nitpick] Grammar in error message: 'Failed to configuration pipe crop' should be 'Failed to configure pipe crop'.
LOG_ERR("Failed to configuration pipe crop");
drivers/video/video_shell.c:1223
- Help text and parser disagree on rectangle syntax: the code expects parentheses
(<left>,<top>)/<width>x<height>
, but the help message omits them. Align documentation with parser behavior.
SHELL_CMD_ARG(selection, &dsub_video_format_dev,
drivers/video/video_shell.c
Outdated
|
||
ret = video_shell_parse_in_out(sh, arg_in_out, &sel.type); | ||
if (ret < 0) { | ||
return -ret; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return -ret; | |
return ret; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected. Same issue within the cmd_video_format function at same place (I copied code from there). I add a commit to fix this in the cmd_video_format function as well.
include/zephyr/drivers/video.h
Outdated
__ASSERT_NO_MSG(sel != NULL); | ||
|
||
api = (const struct video_driver_api *)dev->api; | ||
if (api->set_selection == NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (api->set_selection == NULL) { | |
if (api->get_selection == NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oups, bad copy & paste. Corrected.
drivers/video/video_shell.c
Outdated
static int video_shell_selection_parse_rect(const struct shell *sh, char const *arg_rect, | ||
struct video_rect *rect) | ||
{ | ||
char *end_size = (char *)arg_rect; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please don't cast the const away, as per coding guidelines / MISRA
drivers/video/video_stm32_dcmipp.c
Outdated
|
||
ret = HAL_DCMIPP_PIPE_SetCropConfig(&dcmipp->hdcmipp, pipe->id, &crop_cfg); | ||
if (ret != HAL_OK) { | ||
LOG_ERR("Failed to configuration pipe crop"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOG_ERR("Failed to configuration pipe crop"); | |
LOG_ERR("Failed to configure pipe crop"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for introducing this API! This will be convenient for image sensors as well, which I suppose will use the same API for their cropping region since it is not
I asked a few questions but it seems like being ready. Convenient to have V4L2 as a guideline!
I will give another cycle after your feedback, to make sure I understand what I review. Thank you!
For reference, the linux-side equivalent: |
c7987b2
to
ade64c1
Compare
First force-push to see comments update. |
* | ||
* @param dev Pointer to the device structure for the driver instance. | ||
* @param sel Pointer to a video selection structure | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[non-blocking]
* | |
* Some targets are inter-dependents. For instance, setting a @ref VIDEO_SEL_TGT_CROP will | |
* reset @ref VIDEO_SEL_TGT_COMPOSE to the same size when both are supported. |
Here I propose some minimum hint for users who can't figure out why their firmware work only when calling functions in different order leads to different results. Overkill? Better just point at the V4L2 doc?
Thanks for the explanations earlier!
Addition of selection APIs (set/get) in order to be able to control the crop and compose of a video device. Signed-off-by: Alain Volmat <[email protected]>
1b8693a
to
122b221
Compare
Update the branch to take into consideration the comment from @josuah and also add support for the pipe0 (dump). This update introduce an important modification in behavior compared to previous push in that set_selection(crop) and set_selection(compose) do not necessarily return an error if the parameters cannot be set and instead adjust those parameters. It would be later on up to the application to check the applied settings. This is I think an important behavior point to discuss about, what we would like to end up with. In this version, except when there is really an issue, the crop/compose do not return an error. |
Yes, I think this depends on the HW so hard for an application to know that. That's why I chose to have the driver update the requested crop/compose and let the application know what has been set. But this implie that application check again after getting back the value and take some additional action if the applied setting aren't good for the application. Such behavior is ok I think for a Linux application, but I am not sure if this match well what constraint of a Zephyr application, hence I am still wondering if this should be just "check if this can be applied to the HW and simply reject it if not". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing blocking left I could find! Thank you for the modifications!
/* Compose not available on Pipe0 */ | ||
if (pipe->id == DCMIPP_PIPE0) { | ||
sel->rect = pipe->crop; | ||
goto out; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should ret = -EINVAL
be set here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It depends, this is related to the discussion we are having about returning errors or not.
Here, since there is no compose, basically the applied compose will anyway always be the same as the crop.
A bit similar to when we do a set_frmival on a sensor which cannot change the framerate, we keep returning back the fixed framerate of the sensor.
if (sel->rect.left != 0) { | ||
sel->rect.left = 0; | ||
} | ||
if (sel->rect.top != 0) { | ||
sel->rect.top = 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[non-blocking]
Is the if
needed? It seems like a no-op:
Calling sel->rect.left = 0;
unconditionally would have the same effect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it set left and/or top to 0 if it not 0. if it is already 0 it won't do anything. But yes, always setting left and top to 0 would make the code easier to read/understand I think.
if (err == 0) { | ||
if (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 != -ENOSYS && err < 0) { | ||
LOG_ERR("Unable to set selection compose"); | ||
return 0; | ||
} | ||
} | ||
} else if (err != -ENOSYS && err < 0) { | ||
LOG_ERR("Unable to get selection crop"); | ||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[non-blocking]
Proposal for making the error-handling idioms appear, just a minor nit:
err = video_get_selection(); //
if (err < 0 && err != -ENOSYS) { // well-known C error handling idiom
LOG_ERR("That did not work"); //
return 0; //
} //
if (err == 0) {
err = video_set_selection(); //
if (err < 0 && err != -ENOSYS) { // well-known C error handling idiom
LOG_ERR("That did not work"); //
return 0; //
} //
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah indeed, don't know why I came up with such hard to follow pattern ;(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sometimes what is logical to write is not the same as what is logical to read. I got myself tricked in this exactly earlier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM except the constraint imposed on the sample where I think it should be up to the driver to decide.
Thanks for adding this API. The selection API looks simple enough but the complexity is left in the driver implementation and user's usage, especially its interaction with get/set_format(), e.g. what if format is set first, selection is set first, size does not mismatch, etc. It is left to the driver to decide to tightly couple with set_fmt() or simply return error. And users should always read back their original settings to decide ...
sel.rect.left, sel.rect.top, sel.rect.width, sel.rect.height); | ||
#endif | ||
|
||
#if CONFIG_VIDEO_FRAME_HEIGHT || CONFIG_VIDEO_FRAME_WIDTH |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: In a function, it is recommended to use if (IS_ENABLED())
but it is currently not consistent across the sample
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would also solve the CI issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Added an additionnal prior commit to use if (IS_ENABLED(CONFIG_VIDEO_FRAME_HEIGHT) ... instead of preprocessor.
Add possibility to perform crop on all pipes and compose (downscale) on pixel pipes (endpoint zephyrproject-rtos#1 and endpoint zephyrproject-rtos#2). Rework the code in order to move the downscale control from the set_fmt into the set_selection (compose). Signed-off-by: Alain Volmat <[email protected]>
Add shell handling in order to interact with drivers via the set/get_selection APIs allowing to get/set crop / compose and get HW capabilities such as crop bound / compose bound or native size. Signed-off-by: Alain Volmat <[email protected]>
Correct cmd_video_format return value in case of video_shell_parse_in_out returns a negative value. Signed-off-by: Alain Volmat <[email protected]>
fd2f0c7
to
f1b088c
Compare
Gave up usage of if (IF_ENABLED(...)) since those CONFIG_VIDEO_ .... are not y/n config but values and using them would lead to just never entering into the if true statement. |
Demonstrate the crop/compose API by introducing 4 new CONFIG options in order to define the crop area. Moreover, if the selection API is available and if the targetted size is different from the current crop size, then try to apply a compose in order to reach the targetted format size. Signed-off-by: Alain Volmat <[email protected]>
f1b088c
to
0b9e6db
Compare
|
case VIDEO_SEL_TGT_COMPOSE: | ||
sel->rect = pipe->compose; | ||
break; | ||
case VIDEO_SEL_TGT_CROP_BOUND: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor:
case VIDEO_SEL_TGT_CROP_BOUND: | |
case VIDEO_SEL_TGT_CROP_BOUND: | |
__fallthrough; |
Add a mention to the video_set_selection() and video_get_selection() introduced in zephyrproject-rtos#91878. Signed-off-by: Josuah Demangeon <[email protected]>
Add a mention to the video_set_selection() and video_get_selection() introduced in zephyrproject-rtos#91878. Signed-off-by: Josuah Demangeon <[email protected]>
Add a mention to the video_set_selection() and video_get_selection() introduced in zephyrproject-rtos#91878. Signed-off-by: Josuah Demangeon <[email protected]>
Add a mention to the video_set_selection() and video_get_selection() introduced in #91878. Signed-off-by: Josuah Demangeon <[email protected]>
Add a mention to the video_set_selection() and video_get_selection() introduced in zephyrproject-rtos#91878. Signed-off-by: Josuah Demangeon <[email protected]>
Add a mention to the video_set_selection() and video_get_selection() introduced in zephyrproject-rtos#91878. (cherry picked from commit d491496) Original-Signed-off-by: Josuah Demangeon <[email protected]> GitOrigin-RevId: d491496 Cr-Build-Id: 8709689119827444849 Cr-Build-Url: https://cr-buildbucket.appspot.com/build/8709689119827444849 Copybot-Job-Name: zephyr-main-copybot-downstream Change-Id: I73af2c5c58232bf1086837f435bafd40928478e6 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/zephyr/+/6725779 Commit-Queue: ChromeOS Copybot <[email protected]> Bot-Commit: ChromeOS Copybot <[email protected]> Tested-by: ChromeOS Copybot <[email protected]>
This PR is still a WIP but should already give a good idea of the proposed SELECTION API allowing to the get capabilities of crop/compose as well as control it.
This is based on the Linux V4L2 SELECTION API (available in BSD-Clause): https://docs.kernel.org/6.6/userspace-api/media/v4l/selection-api.html
In order to give a better idea, I've also implemented the shell part as well as DCMIPP driver part (ongoing since only pixel pipes done for the time being, still need a few more code to also add the dump pipe support).
Basically, the setting a crop means that only part of the input is taken into account. The selected crop becomes the default compose size.
Setting a compose size means that the area selected via the crop would get modified (down or up) in order to lead to the rectangle defined by the compose. This lead to the output format at the end.
This leads for example to stuff as what can be seen in dcmipp modifications which is:
In order to give a better idea I've modified the capture sample by adding new CONFIG_ in order to set the crop area and the sample app will, if available in the driver try to set the crop and do the compose to match with the requested output format.
Example of shell output, using DCMIPP driver on the STM32N6:
Upon performing crop / compose the DCMIPP will now generate a 800x480 frame which is a downscale from the a rectangle of 2400x1440 starting at offset 10,10 of an original sensor frame of 2592x1944