-
Notifications
You must be signed in to change notification settings - Fork 7.6k
drivers: video: Add the video shell #88566
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
drivers: video: Add the video shell #88566
Conversation
Because of the limitation of the shell API, a hack was used using This is not expected to take more RAM, only more ROM/Flash. |
11760ae
to
d34be47
Compare
b064217
to
de4e547
Compare
Force-push:
|
drivers/video/video_shell.c
Outdated
#include <stdlib.h> | ||
#include <stdio.h> | ||
#include <ctype.h> | ||
|
||
#include <zephyr/device.h> | ||
#include <zephyr/drivers/video.h> | ||
#include <zephyr/drivers/video-controls.h> | ||
#include <zephyr/sys/byteorder.h> | ||
#include <zephyr/shell/shell.h> |
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: better in alphabetic order
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, I keep forgetting...
if (IS_ENABLED(CONFIG_TEST)) { | ||
ctrl.id = VIDEO_CID_TEST_PATTERN; | ||
video_set_ctrl(video_dev, &ctrl); | ||
} |
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 is unrelated to the video shell change. While it is better to use if
instead of #ifdef
here, this should be in a separate commit so that people will not be confused when reading commit history.
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.
Good point, moved and also converted the other in the process.
if (IS_ENABLED(CONFIG_VIDEO_SHELL)) { | ||
LOG_INF("Letting the user control the device with the video shell"); | ||
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.
I think we should return as soon as possible, right at the beginning of the main function.
- By doing this here, the sample already reserved some video buffers for nothing:
struct video_buffer *buffers[CONFIG_VIDEO_BUFFER_POOL_NUM_MAX], *vbuf;
Users can be very fast (or if something is stuck in the sample) doing something already in the shell before this point, so we waste a significant amount of memory and not enough memory for the shell.
- In fact, the idea is we can use video shell not only on the video device in the sample but also for other video devices (e.g. sw generator). And all the logs information in the sample up to this point (format, framerate, controls) are not needed as user can get them with the shell commands ?
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.
Good point, the video shell already offers a way to print all of the early main content, and the main loop as well.
I moved the if (IS_ENABLED(CONFIG_VIDEO_SHELL))
all the way up. Easy to see that nothing is required for the shell to work that way.
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.
Currently, all the sample main loop does is to just log the buffer fields and stays at that:
LOG_DBG("Got frame %u! size: %u; timestamp %u ms", frame++, vbuf->bytesused,
vbuf->timestamp);
And the video shell actually does not do it. Should I add buffer timestamps to the shell capture
command?
The basic logging of the shell sample can still be useful for troubleshooting when "debug" logs are enabled.
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.
Yes, I think
e992d70
to
1f5c5b0
Compare
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.
VIDEO_EP_ is dropped but I see that the PR still uses it and passes CI (?). That means there is no built-only test cover the video shell. I don't know if we could add a built-only test for it ?
PS : It seems we just need to re-trigger the CI
drivers/video/video_shell.c
Outdated
struct video_format fmt = {0}; | ||
struct video_buffer *buffers[CONFIG_VIDEO_BUFFER_POOL_NUM_MAX] = {NULL}; | ||
struct video_buffer *vbuf = NULL; | ||
char *arg2 = argv[2]; |
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.
As we make use of a local variable here for argv[2], is it better to use a more descriptive name to know what it is ?
drivers/video/video_shell.c
Outdated
enum video_endpoint_id ep, size_t argc, char **argv) | ||
{ | ||
struct video_frmival frmival = {0}; | ||
char *arg0 = argv[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.
idem
drivers/video/video_shell.c
Outdated
enum video_endpoint_id ep, size_t argc, char **argv) | ||
{ | ||
struct video_format fmt = {0}; | ||
char *arg1 = argv[1]; |
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.
idem
drivers/video/video_shell.c
Outdated
struct video_ctrl_query cq = {0}; | ||
struct video_control ctrl; | ||
char menu_name[CONFIG_VIDEO_SHELL_CTRL_NAME_SIZE]; | ||
char *arg1 = argv[1]; |
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.
idem
drivers/video/video_shell.c
Outdated
argv[0], ctrl.id, argv[1], ctrl.val64); | ||
|
||
if (cq.type != VIDEO_CTRL_TYPE_INTEGER64) { | ||
ctrl.val = ctrl.val64; |
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 is not needed as val and val64 are in the same union so they point to the same memory address ?
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.
I have no problem with removing it, but is that also a no-op for big-endian architectures?
[EDIT: newer approach avoids the problem altogether]
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.
Ok, I see now the concern for BE / LE. In fact, it's related to the implementation earlier, if val and val64 are used "normally", this is not a concern (?). It does not matter to me, no need to change if you prefer to do it this way.
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.
I went for something with 1 more line of code but more straightforward.
In hope that makes sense.
Thank you for the feedback.
drivers/video/video_shell.c
Outdated
case VIDEO_CTRL_TYPE_BOOLEAN: | ||
if (strcmp(argv[1], "on") == 0) { | ||
ctrl.val64 = true; | ||
} else if (strcmp(argv[1], "off") == 0) { | ||
ctrl.val64 = false; | ||
} else { | ||
shell_error(sh, "Video control value must be 'on' or 'off', not '%s'", | ||
argv[1]); | ||
return -EINVAL; | ||
} |
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.
Is it simpler to just use 1 and 0 interger instead of "on" and "off" string as v4l2-ctl ? Query-ctrl command can show the min, max, def, cur values so users will not confuse.
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.
Having "on" and "off" permitted the user to discover the type is bool with just 'tab'.
I can offer completion candidates for only 0
and 1
then?
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.
I see, so it's ok as currently then.
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.
I also added "0"
and "1"
as possible input values even though not tab completed. I can also add them as tab completion candidates, very easy.
for (i = 0; cq.menu[i] != NULL; i++) { | ||
video_shell_convert_ctrl_name(cq.menu[i], menu_name, sizeof(menu_name)); | ||
if (strcmp(menu_name, argv[1]) == 0) { | ||
ctrl.val64 = i; |
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.
type menu value is integer, so it should be ctrl.val
(though they can be used interchangeably) ?
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.
I did set everything to ctrl.val64
so that strtoull()
could be used for every type:
ctrl.val64 = strtoull(arg1, &arg1, 10);
But that is confusing, so let's get back to something more readable.
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's not confusing, I see the intention, just a bit unusual where I see ctrl.val = ctrl.val64
as commented above. Keep the implementation as is if you see it's more convenient.
drivers/video/video_shell.c
Outdated
/* Current video endpoint, used for tab completion */ | ||
static enum video_endpoint_id video_shell_ep = VIDEO_EP_NONE; |
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.
VIDEO_EP_ is dropped so this need to be rebased. Idem for others.
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.
Hurray!
8582c26
to
0d41a44
Compare
drivers/video/video_shell.c
Outdated
|
||
num_buffers = strtoull(arg2, &arg2, 10); | ||
if (*arg2 != '\0') { | ||
shell_error(sh, "Invalid integer '%s' for this type", argv[1]); |
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 should have been argv[2]
.
drivers/video/video_shell.c
Outdated
argv[0], ctrl.id, argv[1], ctrl.val64); | ||
|
||
if (cq.type != VIDEO_CTRL_TYPE_INTEGER64) { | ||
ctrl.val = ctrl.val64; |
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.
I went for something with 1 more line of code but more straightforward.
In hope that makes sense.
Thank you for the feedback.
drivers/video/video_shell.c
Outdated
case VIDEO_CTRL_TYPE_BOOLEAN: | ||
if (strcmp(argv[1], "on") == 0) { | ||
ctrl.val64 = true; | ||
} else if (strcmp(argv[1], "off") == 0) { | ||
ctrl.val64 = false; | ||
} else { | ||
shell_error(sh, "Video control value must be 'on' or 'off', not '%s'", | ||
argv[1]); | ||
return -EINVAL; | ||
} |
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.
I also added "0"
and "1"
as possible input values even though not tab completed. I can also add them as tab completion candidates, very easy.
Force-push:
Tested again each command against the
Then on another terminal, replacing
|
|
Introduce the video shell and implement some video shell commands. Make use of the various querying API to implement tab-completion, and validiate the data, as well as convert string names into integers. Commands provided: frmival, format, ctrl, start, stop, capture Signed-off-by: Josuah Demangeon <me@josuah.net>
Modify the capture sample to only run the video shell when the user enables it with -DCONFIG_VIDEO_SHELL=y, as an alternative way to trigger captures. Signed-off-by: Josuah Demangeon <me@josuah.net>
Convert #ifdef CONFIG_TEST into if (IS_ENABLED(CONFIG_TEST)) to improve readability. Signed-off-by: Josuah Demangeon <me@josuah.net>
Dependencies:
Replaces:
Now that we have a nice shell control querying API, it is possible to tab-complete in-depth every control value.
To test on
native_sim
withVIDEO_SW_GENERATOR
:On another terminal, using your favorite serial console client, and likely
COM#
on Windows instead of/dev/pts/3
: