Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions host/class/uvc/usb_host_uvc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Added NV12 stream format parsing for UVC uncompressed descriptors.

### Fixed

- Fixed regression from version 2.5.0 where unreasonably large URBs could be allocated, leading to out-of-memory scenarios. Now, if urb_size == 0, we allocate URB of size 4x MPS. For other urb_sizes, user's value is used to provide flexibility.
- Fixed unsupported UVC formats leaking into the frame list when descriptor parsing returns an invalid format.

## [2.5.0] - 2026-04-13

Expand Down
1 change: 1 addition & 0 deletions host/class/uvc/usb_host_uvc/include/usb/uvc_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ enum uvc_host_stream_format {
UVC_VS_FORMAT_YUY2, /*!< YUY2 stream format. */
UVC_VS_FORMAT_H264, /*!< H.264 stream format. */
UVC_VS_FORMAT_H265, /*!< H.265 stream format. */
UVC_VS_FORMAT_NV12, /*!< NV12 stream format. */
};

/**
Expand Down
8 changes: 6 additions & 2 deletions host/class/uvc/usb_host_uvc/uvc_descriptor_parsing.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ int uvc_desc_parse_format(const uvc_format_desc_t *format_desc)
// We do not check full guid, but only the first 4 characters that show human readable format
if (strncmp(guid, "YUY2", 4) == 0) {
ret = UVC_VS_FORMAT_YUY2;
} else if (strncmp(guid, "NV12", 4) == 0) {
ret = UVC_VS_FORMAT_NV12;
}
break;
}
Expand Down Expand Up @@ -456,10 +458,11 @@ esp_err_t uvc_desc_get_frame_list(const usb_config_desc_t *config_desc, uint8_t
}

const uvc_format_desc_t *this_format = (const uvc_format_desc_t *)(current_desc);
enum uvc_host_stream_format format_type = uvc_desc_parse_format(this_format);
if (0 > format_type) { // Undefined format
int parsed_format = uvc_desc_parse_format(this_format);
if (parsed_format < 0) { // Undefined format
continue;
}
enum uvc_host_stream_format format_type = parsed_format;

num_frame += this_format->bNumFrameDescriptors;

Expand All @@ -485,6 +488,7 @@ esp_err_t uvc_desc_get_frame_list(const usb_config_desc_t *config_desc, uint8_t
frame_info->v_res = this_frame->wHeight;
switch (format_type) {
case UVC_VS_FORMAT_YUY2:
case UVC_VS_FORMAT_NV12:
case UVC_VS_FORMAT_MJPEG:
frame_info->default_interval = this_frame->mjpeg_uncompressed.dwDefaultFrameInterval;
frame_info->interval_type = this_frame->mjpeg_uncompressed.bFrameIntervalType;
Expand Down
Loading