Skip to content

Commit 01a30a5

Browse files
committed
WIP/Experiment - Camera Viewport and Snapshot
Note: this all uses the Zephyr updates from my PR zephyrproject-rtos/zephyr#93797 Which I added to the STM dcmi driver the ability to have the camera work in snapshot mode instead of in continuous video mode. This allows for example that we start the camera it grabs a frame and stops, we then take the buffer and process it, and repeat this. This helps minimize how much the SDRAM gets used concurrently. In addition, I added to the VIDEO_STM32_DCMI and GC2145 the ability to use some of the new set_selection and get_selection code that was added for the DCMIPP. In particular the DCMI simply forwards these messages to the camera if it defined thise apis... And with this it allows you to setup a viewport into the frame. For example: You can setup the frame on the GC2145 to be 800x600 and then define a view port to be 480x320 to fill an ST7796/ILI9486 tft display or you could do it 400x240 to half fill the GIGA display. You can also move that view port around within the frame (pan) I have examples that do this on Portenta H7 on the ST7796 display and another one that does this on the GIGA display shield. Still WIP as we probably need to refine the APIS and the like
1 parent 1821cb9 commit 01a30a5

File tree

3 files changed

+156
-10
lines changed

3 files changed

+156
-10
lines changed

libraries/Camera/src/camera.cpp

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,12 @@ Camera::Camera() : vdev(NULL), byte_swap(false), yuv_to_gray(false) {
4646
}
4747
}
4848

49+
4950
bool Camera::begin(uint32_t width, uint32_t height, uint32_t pixformat, bool byte_swap) {
51+
return begin(width, height, width, height, pixformat, byte_swap);
52+
}
53+
54+
bool Camera::begin(uint32_t width, uint32_t height, uint32_t crop_width, uint32_t crop_height, uint32_t pixformat, bool byte_swap) {
5055
#if DT_HAS_CHOSEN(zephyr_camera)
5156
this->vdev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera));
5257
#endif
@@ -75,14 +80,14 @@ bool Camera::begin(uint32_t width, uint32_t height, uint32_t pixformat, bool byt
7580
return false;
7681
}
7782

78-
for (size_t i=0; caps.format_caps[i].pixelformat != NULL; i++) {
83+
for (size_t i=0; caps.format_caps[i].pixelformat != 0; i++) {
7984
const struct video_format_cap *fcap = &caps.format_caps[i];
80-
if (fcap->width_min == width &&
81-
fcap->height_min == height &&
85+
if (fcap->width_min <= width && fcap->width_max >= width &&
86+
fcap->height_min <= height && fcap->height_max >= height &&
8287
fcap->pixelformat == pixformat) {
8388
break;
8489
}
85-
if (caps.format_caps[i+1].pixelformat == NULL) {
90+
if (caps.format_caps[i+1].pixelformat == 0) {
8691
Serial.println("The specified format is not supported");
8792
return false;
8893
}
@@ -101,6 +106,24 @@ bool Camera::begin(uint32_t width, uint32_t height, uint32_t pixformat, bool byt
101106
return false;
102107
}
103108

109+
// optionally set the crop values
110+
if (width != crop_width || height != crop_height) {
111+
struct video_selection vselCrop;
112+
vselCrop.type = VIDEO_BUF_TYPE_OUTPUT;
113+
vselCrop.target = VIDEO_SEL_TGT_CROP;
114+
vselCrop.rect.left = (width - crop_width) / 2;
115+
vselCrop.rect.top = (height - crop_height) / 2;
116+
vselCrop.rect.width = crop_width;
117+
vselCrop.rect.height = crop_height;;
118+
119+
int ret;
120+
if ((ret = setSelection(&vselCrop)) != 0) {
121+
printk("ERROR: %d\n", ret);
122+
}
123+
}
124+
// this should compute the sizes needed.
125+
video_get_format(this->vdev, &fmt);
126+
104127
// Allocate video buffers.
105128
for (size_t i = 0; i < ARRAY_SIZE(this->vbuf); i++) {
106129
this->vbuf[i] = video_buffer_aligned_alloc(fmt.pitch * fmt.height,
@@ -126,11 +149,11 @@ bool Camera::grabFrame(FrameBuffer &fb, uint32_t timeout) {
126149
if (this->vdev == NULL) {
127150
return false;
128151
}
129-
152+
//printk("Camera::grabFrame called\n");
130153
if (video_dequeue(this->vdev, &fb.vbuf, K_MSEC(timeout))) {
131154
return false;
132155
}
133-
156+
//printk("video_dequeue returned :%p\n", fb.vbuf->buffer);
134157
if (this->byte_swap) {
135158
uint16_t *pixels = (uint16_t *) fb.vbuf->buffer;
136159
for (size_t i=0; i<fb.vbuf->bytesused / 2; i++) {
@@ -154,7 +177,10 @@ bool Camera::releaseFrame(FrameBuffer &fb) {
154177
return false;
155178
}
156179

157-
if (video_enqueue(this->vdev, fb.vbuf)) {
180+
int ret;
181+
//printk("Camera::ReleaseFrame called\n");
182+
if (ret = video_enqueue(this->vdev, fb.vbuf)) {
183+
printk("Failed to enqueue buffer %d\n", ret);
158184
return false;
159185
}
160186

@@ -170,3 +196,52 @@ bool Camera::setHorizontalMirror(bool mirror_enable) {
170196
struct video_control ctrl = {.id = VIDEO_CID_HFLIP, .val = mirror_enable};
171197
return video_set_ctrl(this->vdev, &ctrl) == 0;
172198
}
199+
200+
int Camera::setSelection(struct video_selection *sel) {
201+
return video_set_selection(vdev, sel);
202+
}
203+
204+
/**
205+
* @brief Get video selection (crop/compose).
206+
*
207+
* Retrieve the current settings related to the crop and compose of the video device.
208+
* This can also be used to read the native size of the input stream of the video
209+
* device.
210+
* This function can be used to read crop / compose capabilities of the device prior
211+
* to performing configuration via the @ref video_set_selection api.
212+
*
213+
* @param sel Pointer to a video selection structure, @c type and @c target set by the caller
214+
*
215+
* @retval 0 Is successful.
216+
* @retval -EINVAL If parameters are invalid.
217+
* @retval -ENOTSUP If format is not supported.
218+
* @retval -EIO General input / output error.
219+
*/
220+
int Camera::getSelection(struct video_selection *sel) {
221+
return video_get_selection(vdev, sel);
222+
}
223+
224+
/**
225+
* @brief returns if snapshot mode is turned on or off.
226+
*
227+
* @param snapshot_mode pointer to Turn Snaphsot mode on or off..
228+
*/
229+
int Camera::getSnapshotMode(bool *snapshot_mode) {
230+
#if DT_HAS_CHOSEN(zephyr_camera)
231+
this->vdev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera));
232+
#endif
233+
return video_get_snapshot_mode(vdev, snapshot_mode);
234+
}
235+
236+
/**
237+
* @brief Function pointer type for video_set_snapshot_mode()
238+
*
239+
* @param snapshot_mode Turn Snaphsot mode on or off..
240+
*/
241+
int Camera::setSnapshotMode(bool snapshot_mode) {
242+
#if DT_HAS_CHOSEN(zephyr_camera)
243+
this->vdev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera));
244+
#endif
245+
return video_set_snapshot_mode(vdev, snapshot_mode);
246+
}
247+

libraries/Camera/src/camera.h

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,19 @@ class FrameBuffer {
6262
friend class Camera;
6363
};
6464

65+
66+
// bugbug temporary
67+
#include <zephyr/drivers/video.h>
68+
6569
/**
6670
* @class Camera
6771
* @brief The main class for controlling a camera.
6872
*/
6973
class Camera {
7074
private:
75+
const struct device *vdev;
7176
bool byte_swap;
7277
bool yuv_to_gray;
73-
const struct device *vdev;
7478
struct video_buffer *vbuf[CONFIG_VIDEO_BUFFER_POOL_NUM_MAX];
7579

7680
public:
@@ -90,6 +94,19 @@ class Camera {
9094
*/
9195
bool begin(uint32_t width, uint32_t height, uint32_t pixformat = CAMERA_RGB565, bool byte_swap = false);
9296

97+
/**
98+
* @brief Initialize the camera.
99+
*
100+
* @param width Frame width in pixels.
101+
* @param height Frame height in pixels.
102+
* @param crop_width crop width in pixels.
103+
* @param crop_height crop height in pixels.
104+
* @param pixformat Initial pixel format (default: CAMERA_RGB565).
105+
* @param byte_swap Enable byte swapping (default: false).
106+
* @return true if the camera is successfully initialized, otherwise false.
107+
*/
108+
bool begin(uint32_t width, uint32_t height, uint32_t crop_width, uint32_t crop_height, uint32_t pixformat = CAMERA_RGB565, bool byte_swap = false);
109+
93110
/**
94111
* @brief Capture a frame.
95112
*
@@ -122,6 +139,59 @@ class Camera {
122139
* @return true on success, false on failure.
123140
*/
124141
bool setHorizontalMirror(bool mirror_enable);
142+
143+
144+
/* Experiments to be able to set crop and the like */
145+
/**
146+
* @brief Set video selection (crop/compose).
147+
*
148+
* Configure the optional crop and compose feature of a video device.
149+
* Crop is first applied on the input frame, and the result of that crop is applied
150+
* to the compose. The result of the compose (width/height) is equal to the format
151+
* width/height given to the @ref video_set_format function.
152+
*
153+
* Some targets are inter-dependents. For instance, setting a @ref VIDEO_SEL_TGT_CROP will
154+
* reset @ref VIDEO_SEL_TGT_COMPOSE to the same size.
155+
*
156+
* @param sel Pointer to a video selection structure
157+
*
158+
* @retval 0 Is successful.
159+
* @retval -EINVAL If parameters are invalid.
160+
* @retval -ENOTSUP If format is not supported.
161+
* @retval -EIO General input / output error.
162+
*/
163+
int setSelection(struct video_selection *sel);
164+
/**
165+
* @brief Get video selection (crop/compose).
166+
*
167+
* Retrieve the current settings related to the crop and compose of the video device.
168+
* This can also be used to read the native size of the input stream of the video
169+
* device.
170+
* This function can be used to read crop / compose capabilities of the device prior
171+
* to performing configuration via the @ref video_set_selection api.
172+
*
173+
* @param sel Pointer to a video selection structure, @c type and @c target set by the caller
174+
*
175+
* @retval 0 Is successful.
176+
* @retval -EINVAL If parameters are invalid.
177+
* @retval -ENOTSUP If format is not supported.
178+
* @retval -EIO General input / output error.
179+
*/
180+
int getSelection(struct video_selection *sel);
181+
182+
/**
183+
* @brief returns if snapshot mode is turned on or off.
184+
*
185+
* @param snapshot_mode pointer to Turn Snaphsot mode on or off..
186+
*/
187+
int getSnapshotMode(bool *snapshot_mode);
188+
189+
/**
190+
* @brief Function pointer type for video_set_snapshot_mode()
191+
*
192+
* @param snapshot_mode Turn Snaphsot mode on or off..
193+
*/
194+
int setSnapshotMode(bool snapshot_mode);
125195
};
126196

127197
#endif // __CAMERA_H__

variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.conf

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ CONFIG_ENTROPY_GENERATOR=y
3535
CONFIG_TEST_RANDOM_GENERATOR=y
3636

3737
CONFIG_VIDEO=y
38-
CONFIG_VIDEO_LOG_LEVEL_DBG=y
38+
CONFIG_VIDEO_LOG_LEVEL_DBG=n
3939
CONFIG_VIDEO_STM32_DCMI=y
40-
CONFIG_VIDEO_BUFFER_POOL_NUM_MAX=3
40+
CONFIG_VIDEO_BUFFER_POOL_NUM_MAX=1
4141
CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=614400
4242
CONFIG_VIDEO_BUFFER_POOL_ALIGN=32
4343
CONFIG_VIDEO_BUFFER_USE_SHARED_MULTI_HEAP=y
@@ -61,6 +61,7 @@ CONFIG_BT_CTLR_ADV_EXT=y
6161
CONFIG_BT_CTLR_ADV_PERIODIC=y
6262
CONFIG_BT_CTLR_DTM_HCI=y
6363
CONFIG_CYW4343W_MURATA_1DX=y
64+
CONFIG_BT_HCI_DRIVER_LOG_LEVEL_DBG=n
6465
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
6566
CONFIG_BT_RX_STACK_SIZE=4096
6667
CONFIG_BT_HCI_TX_STACK_SIZE=4096

0 commit comments

Comments
 (0)