-
Notifications
You must be signed in to change notification settings - Fork 8.2k
samples: drivers: video: add capture to lvgl sample #71463
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
Merged
nashif
merged 1 commit into
zephyrproject-rtos:main
from
CharlesDias:video_capture_to_lcd
Sep 26, 2024
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,4 +16,5 @@ supported: | |
| - watchdog | ||
| - usb | ||
| - qspi | ||
| - video | ||
| vendor: weact | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| cmake_minimum_required(VERSION 3.20.0) | ||
| find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) | ||
| project(video_capture) | ||
|
|
||
| FILE(GLOB app_sources src/*.c) | ||
| target_sources(app PRIVATE ${app_sources}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # VIDEO resolution settings | ||
|
|
||
| # Copyright (c) 2024 Charles Dias <[email protected]> | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| source "Kconfig.zephyr" | ||
|
|
||
| config VIDEO_WIDTH | ||
| int "Define the width of the video" | ||
| default 320 | ||
|
|
||
| config VIDEO_HEIGHT | ||
| int "Define the height of the video" | ||
| default 240 | ||
|
|
||
| config VIDEO_HFLIP | ||
| bool "Horizontal flip" | ||
| default n | ||
|
|
||
| config VIDEO_VFLIP | ||
| bool "Vertical flip" | ||
| default n |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| .. zephyr:code-sample:: video-capture-to-lvgl | ||
| :name: Video capture to LVGL | ||
| :relevant-api: video_interface | ||
|
|
||
| Capture video frames and display them on an LCD using LVGL. | ||
|
|
||
| Description | ||
| *********** | ||
|
|
||
| The application uses the :ref:`Video API <video_api>` to retrieve video frames from | ||
| a video capture device, write a frame count message to the console, and then send | ||
| the frame to an LCD display. | ||
|
|
||
| Requirements | ||
| ************ | ||
|
|
||
| This sample requires a supported :ref:`video capture device <video_api>` (e.g., a camera) | ||
| and a :ref:`display <display_api>`. | ||
|
|
||
| Wiring | ||
| ****** | ||
|
|
||
| On the `WeAct Studio STM32H743`_, connect the OV2640 camera module and the 0.96" ST7735 | ||
| TFT LCD display. Connect a USB cable from a host to the micro USB-C connector on the | ||
| board to receive console output messages. | ||
|
|
||
| Building and Running | ||
| ******************** | ||
|
|
||
| For :ref:`mini_stm32h743`, build this sample application with the following commands: | ||
|
|
||
| .. zephyr-app-commands:: | ||
| :zephyr-app: samples/drivers/video/capture_to_lvgl/ | ||
| :board: mini_stm32h743 | ||
| :shield: weact_ministm32h7xx_ov2640 | ||
| :goals: build flash | ||
| :gen-args: -DCONFIG_BOOT_DELAY=2000 | ||
| :compact: | ||
|
|
||
| Sample Output | ||
| ============= | ||
|
|
||
| .. code-block:: console | ||
|
|
||
| [00:00:02.779,000] <inf> main: - Device name: dcmi@48020000 | ||
| [00:00:02.779,000] <inf> main: - Capabilities: | ||
| [00:00:02.779,000] <inf> main: RGBP width [160; 160; 0] height [120; 120; 0] | ||
| [00:00:02.779,000] <inf> main: RGBP width [176; 176; 0] height [144; 144; 0] | ||
| [00:00:02.780,000] <inf> main: RGBP width [240; 240; 0] height [160; 160; 0] | ||
| [00:00:02.780,000] <inf> main: RGBP width [320; 320; 0] height [240; 240; 0] | ||
| [00:00:02.780,000] <inf> main: RGBP width [352; 352; 0] height [288; 288; 0] | ||
| [00:00:02.780,000] <inf> main: RGBP width [640; 640; 0] height [480; 480; 0] | ||
| [00:00:02.780,000] <inf> main: RGBP width [800; 800; 0] height [600; 600; 0] | ||
| [00:00:02.780,000] <inf> main: RGBP width [1024; 1024; 0] height [768; 768; 0] | ||
| [00:00:02.780,000] <inf> main: RGBP width [1280; 1280; 0] height [1024; 1024; 0] | ||
| [00:00:02.780,000] <inf> main: RGBP width [1600; 1600; 0] height [1200; 1200; 0] | ||
| [00:00:02.780,000] <inf> main: JPEG width [160; 160; 0] height [120; 120; 0] | ||
| [00:00:02.780,000] <inf> main: JPEG width [176; 176; 0] height [144; 144; 0] | ||
| [00:00:02.780,000] <inf> main: JPEG width [240; 240; 0] height [160; 160; 0] | ||
| [00:00:02.780,000] <inf> main: JPEG width [320; 320; 0] height [240; 240; 0] | ||
| [00:00:02.780,000] <inf> main: JPEG width [352; 352; 0] height [288; 288; 0] | ||
| [00:00:02.780,000] <inf> main: JPEG width [640; 640; 0] height [480; 480; 0] | ||
| [00:00:02.780,000] <inf> main: JPEG width [800; 800; 0] height [600; 600; 0] | ||
| [00:00:02.780,000] <inf> main: JPEG width [1024; 1024; 0] height [768; 768; 0] | ||
| [00:00:02.780,000] <inf> main: JPEG width [1280; 1280; 0] height [1024; 1024; 0] | ||
| [00:00:02.780,000] <inf> main: JPEG width [1600; 1600; 0] height [1200; 1200; 0] | ||
| [00:00:02.852,000] <inf> main: - Format: RGBP 160x120 320 | ||
| [00:00:02.854,000] <inf> main: - Capture started | ||
|
|
||
| References | ||
| ********** | ||
|
|
||
| .. _WeAct Studio STM32H743: https://github.com/WeActStudio/MiniSTM32H7xx | ||
11 changes: 11 additions & 0 deletions
11
samples/drivers/video/capture_to_lvgl/boards/mini_stm32h743.conf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # | ||
| # Copyright (c) 2024 Charles Dias <[email protected]> | ||
| # | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # | ||
|
|
||
| CONFIG_LOG_BUFFER_SIZE=2048 | ||
|
|
||
| CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=102400 | ||
| CONFIG_VIDEO_WIDTH=160 | ||
| CONFIG_VIDEO_HEIGHT=120 |
10 changes: 10 additions & 0 deletions
10
samples/drivers/video/capture_to_lvgl/boards/mini_stm32h743.overlay
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| /* | ||
| * Copyright (c) 2024 Charles Dias <[email protected]> | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| * | ||
| */ | ||
|
|
||
| &st7735r_160x80 { | ||
| madctl = <184>; /* Rotate the image 180 degrees. */ | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| CONFIG_VIDEO=y | ||
| CONFIG_VIDEO_SW_GENERATOR=y | ||
|
|
||
| CONFIG_PRINTK=y | ||
| CONFIG_LOG=y | ||
|
|
||
| CONFIG_MAIN_STACK_SIZE=4096 | ||
|
|
||
| CONFIG_DISPLAY=y | ||
| CONFIG_DISPLAY_LOG_LEVEL_ERR=y | ||
|
|
||
| CONFIG_LVGL=y | ||
| CONFIG_LV_CONF_MINIMAL=y | ||
| CONFIG_LV_MEM_CUSTOM=y | ||
| CONFIG_LV_USE_IMG=y | ||
| CONFIG_LV_Z_MEM_POOL_SIZE=16384 | ||
| CONFIG_LV_USE_PERF_MONITOR=y |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| sample: | ||
| name: Video capture to LVGL | ||
| tests: | ||
| sample.video.capture_to_lvgl: | ||
| tags: | ||
| - video | ||
| - samples | ||
| platform_allow: | ||
| - mini_stm32h743 | ||
| depends_on: video | ||
erwango marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| integration_platforms: | ||
| - mini_stm32h743 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| /* | ||
| * Copyright (c) 2024 Charles Dias <[email protected]> | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| #include <zephyr/kernel.h> | ||
| #include <zephyr/device.h> | ||
| #include <zephyr/drivers/display.h> | ||
| #include <zephyr/drivers/video.h> | ||
| #include <lvgl.h> | ||
|
|
||
| #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL | ||
| #include <zephyr/logging/log.h> | ||
| LOG_MODULE_REGISTER(main); | ||
|
|
||
| #define VIDEO_DEV_SW "VIDEO_SW_GENERATOR" | ||
|
|
||
| int main(void) | ||
| { | ||
| struct video_buffer *buffers[2], *vbuf; | ||
| const struct device *display_dev; | ||
| struct video_format fmt; | ||
| struct video_caps caps; | ||
| const struct device *video_dev; | ||
| size_t bsize; | ||
| int i = 0; | ||
|
|
||
| display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display)); | ||
| if (!device_is_ready(display_dev)) { | ||
| LOG_ERR("Device not ready, aborting test"); | ||
| return 0; | ||
| } | ||
|
|
||
| #if DT_HAS_CHOSEN(zephyr_camera) | ||
| video_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera)); | ||
| if (!device_is_ready(video_dev)) { | ||
| LOG_ERR("%s device is not ready", video_dev->name); | ||
| return 0; | ||
| } | ||
| #else | ||
| video_dev = device_get_binding(VIDEO_DEV_SW); | ||
| if (video_dev == NULL) { | ||
| LOG_ERR("%s device not found", VIDEO_DEV_SW); | ||
| return 0; | ||
| } | ||
| #endif | ||
|
|
||
| LOG_INF("- Device name: %s", video_dev->name); | ||
|
|
||
| /* Get capabilities */ | ||
| if (video_get_caps(video_dev, VIDEO_EP_OUT, &caps)) { | ||
| LOG_ERR("Unable to retrieve video capabilities"); | ||
| return 0; | ||
| } | ||
|
|
||
| LOG_INF("- Capabilities:"); | ||
| while (caps.format_caps[i].pixelformat) { | ||
| const struct video_format_cap *fcap = &caps.format_caps[i]; | ||
| /* four %c to string */ | ||
| LOG_INF(" %c%c%c%c width [%u; %u; %u] height [%u; %u; %u]", | ||
| (char)fcap->pixelformat, (char)(fcap->pixelformat >> 8), | ||
| (char)(fcap->pixelformat >> 16), (char)(fcap->pixelformat >> 24), | ||
| fcap->width_min, fcap->width_max, fcap->width_step, fcap->height_min, | ||
| fcap->height_max, fcap->height_step); | ||
| i++; | ||
| } | ||
|
|
||
| /* Get default/native format */ | ||
| if (video_get_format(video_dev, VIDEO_EP_OUT, &fmt)) { | ||
| LOG_ERR("Unable to retrieve video format"); | ||
| return 0; | ||
| } | ||
|
|
||
| /* Set format */ | ||
| fmt.width = CONFIG_VIDEO_WIDTH; | ||
| fmt.height = CONFIG_VIDEO_HEIGHT; | ||
| fmt.pitch = fmt.width * 2; | ||
| fmt.pixelformat = VIDEO_PIX_FMT_RGB565; | ||
|
|
||
| if (video_set_format(video_dev, VIDEO_EP_OUT, &fmt)) { | ||
| LOG_ERR("Unable to set up video format"); | ||
| return 0; | ||
| } | ||
|
|
||
| LOG_INF("- Format: %c%c%c%c %ux%u %u", (char)fmt.pixelformat, (char)(fmt.pixelformat >> 8), | ||
| (char)(fmt.pixelformat >> 16), (char)(fmt.pixelformat >> 24), fmt.width, fmt.height, | ||
| fmt.pitch); | ||
|
|
||
| /* Size to allocate for each buffer */ | ||
| bsize = fmt.pitch * fmt.height; | ||
|
|
||
| /* Alloc video buffers and enqueue for capture */ | ||
| for (i = 0; i < ARRAY_SIZE(buffers); i++) { | ||
| buffers[i] = video_buffer_alloc(bsize); | ||
| if (buffers[i] == NULL) { | ||
| LOG_ERR("Unable to alloc video buffer"); | ||
| return 0; | ||
| } | ||
|
|
||
| video_enqueue(video_dev, VIDEO_EP_OUT, buffers[i]); | ||
| } | ||
|
|
||
| #ifdef CONFIG_VIDEO_HFLIP | ||
| /* Video flip image horizontally */ | ||
| if (video_set_ctrl(video_dev, VIDEO_CID_HFLIP, (void *)1)) { | ||
| LOG_ERR("Unable to set video control (HFLIP)"); | ||
| return 0; | ||
| } | ||
| #endif | ||
|
|
||
| #ifdef CONFIG_VIDEO_VFLIP | ||
| /* Video flip image vertically */ | ||
| if (video_set_ctrl(video_dev, VIDEO_CID_VFLIP, (void *)1)) { | ||
| LOG_ERR("Unable to set video control (VFLIP)"); | ||
| return 0; | ||
| } | ||
| #endif | ||
|
|
||
| /* Start video capture */ | ||
| if (video_stream_start(video_dev)) { | ||
| LOG_ERR("Unable to start capture (interface)"); | ||
| return 0; | ||
| } | ||
|
|
||
| display_blanking_off(display_dev); | ||
|
|
||
| const lv_img_dsc_t video_img = { | ||
| .header.always_zero = 0, | ||
| .header.w = CONFIG_VIDEO_WIDTH, | ||
| .header.h = CONFIG_VIDEO_HEIGHT, | ||
| .data_size = CONFIG_VIDEO_WIDTH * CONFIG_VIDEO_HEIGHT * sizeof(lv_color_t), | ||
| .header.cf = LV_IMG_CF_TRUE_COLOR, | ||
| .data = (const uint8_t *)buffers[0]->buffer, | ||
| }; | ||
|
|
||
| lv_obj_t *screen = lv_img_create(lv_scr_act()); | ||
|
|
||
| LOG_INF("- Capture started"); | ||
|
|
||
| /* Grab video frames */ | ||
| while (1) { | ||
| int err; | ||
|
|
||
| err = video_dequeue(video_dev, VIDEO_EP_OUT, &vbuf, K_FOREVER); | ||
| if (err) { | ||
| LOG_ERR("Unable to dequeue video buf"); | ||
| return 0; | ||
| } | ||
|
|
||
| lv_img_set_src(screen, &video_img); | ||
| lv_obj_align(screen, LV_ALIGN_BOTTOM_LEFT, 0, 0); | ||
|
|
||
| lv_task_handler(); | ||
|
|
||
| err = video_enqueue(video_dev, VIDEO_EP_OUT, vbuf); | ||
| if (err) { | ||
| LOG_ERR("Unable to requeue video buf"); | ||
| return 0; | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.