RTOS UVC Host Guide#
Overview#
The RT-Smart user-space UVC host APIs use the uvc_host_* prefix, and image formats are described with FOURCC.
Related sample directories:
src/rtsmart/examples/mpp/sample_uvc_hostsrc/rtsmart/examples/mpp/sample_uvc_dev_picturesrc/rtsmart/examples/mpp/sample_uvc_dev_vicap
Currently supported input formats:
USBH_VIDEO_FOURCC_YUY2USBH_VIDEO_FOURCC_UYVYUSBH_VIDEO_FOURCC_NV12USBH_VIDEO_FOURCC_I420USBH_VIDEO_FOURCC_MJPEG
Among them:
MJPEGis a compressed stream formatYUY2,UYVY,NV12, andI420are raw pixel formats
Data Structures#
User-space header:
src/rtsmart/mpp/userapps/api/mpi_uvc_api.h
struct uvc_format#
struct uvc_format {
unsigned int width;
unsigned int height;
unsigned int fourcc;
unsigned int frameinterval;
};
Field description:
Field |
Description |
|---|---|
|
Requested or negotiated image width |
|
Requested or negotiated image height |
|
Image format, using |
|
Frame interval in |
Notes:
uvc_host_init()uses this structure both for user input and for returning the final negotiated mode.If the requested width, height, or frame rate cannot be matched exactly, the lower layer returns the actual negotiated result.
struct uvc_frame#
struct uvc_frame {
unsigned int index;
unsigned int bytesused;
char *userptr;
union {
k_video_frame_info v_info;
k_vdec_stream v_stream;
};
};
Field description:
Field |
Description |
|---|---|
|
UVC buffer index for the current frame |
|
Valid data length in bytes |
|
User-space virtual address of the current frame |
|
Video-frame info for raw image data |
|
VDEC input info for |
Notes:
Internal mapping fields such as
lengthandoffsetare not exposed in the user-space structure.userptris valid only while the frame is held by the application.After
uvc_host_put_frame()is called,userptrmust not be used again.For
MJPEG,bytesusedis typically used when writing the compressed data directly to a file.
FOURCC Definitions#
#define USBH_VIDEO_FOURCC(a, b, c, d) \
((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | \
((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24))
#define USBH_VIDEO_FOURCC_YUY2 USBH_VIDEO_FOURCC('Y', 'U', 'Y', '2')
#define USBH_VIDEO_FOURCC_UYVY USBH_VIDEO_FOURCC('U', 'Y', 'V', 'Y')
#define USBH_VIDEO_FOURCC_NV12 USBH_VIDEO_FOURCC('N', 'V', '1', '2')
#define USBH_VIDEO_FOURCC_I420 USBH_VIDEO_FOURCC('I', '4', '2', '0')
#define USBH_VIDEO_FOURCC_MJPEG USBH_VIDEO_FOURCC('M', 'J', 'P', 'G')
API Reference#
int uvc_host_init(struct uvc_format *fmt);#
Initialize the UVC host device.
int uvc_host_init(struct uvc_format *fmt);
Notes:
fmtcarries the requestedwidth,height,fourcc, andframeinterval.After successful initialization,
fmtis updated with the negotiated mode.It is recommended to complete VB initialization before using this API.
Return value:
0on successnegative value on failure
int uvc_host_start_stream(void);#
Start the UVC video stream.
int uvc_host_start_stream(void);
Return value:
0on successnegative value on failure
int uvc_host_get_frame(struct uvc_frame *frame, unsigned int timeout_ms);#
Get one UVC frame.
int uvc_host_get_frame(struct uvc_frame *frame, unsigned int timeout_ms);
Notes:
The call blocks until a frame is received or the timeout expires.
On success,
frameis filled with the buffer info anduserptr.Every successful
uvc_host_get_frame()must be paired withuvc_host_put_frame().
Return value:
0on successnegative value on failure
int uvc_host_put_frame(struct uvc_frame *frame);#
Return one frame buffer to the driver.
int uvc_host_put_frame(struct uvc_frame *frame);
Notes:
After the buffer is returned, the driver may reuse it.
userptrmust not be accessed after this call.
void uvc_host_exit(void);#
Close the UVC device and release resources.
void uvc_host_exit(void);
Notes:
If streaming has already started,
uvc_host_exit()performs the stream cleanup.There is currently no separate
uvc_host_stop_stream()API.
int uvc_host_get_devinfo(char *info, int len);#
Query device vendor and product information.
int uvc_host_get_devinfo(char *info, int len);
Notes:
On success, the returned string is typically in the form
vendor#product.The API can open the device temporarily even if
uvc_host_init()has not been called yet.
int uvc_host_get_formats(struct uvc_format **fmts);#
Enumerate all supported device modes.
int uvc_host_get_formats(struct uvc_format **fmts);
Notes:
The return value is the number of formats.
*fmtsis allocated internally and must be released withuvc_host_free_formats().Each
uvc_formatentry corresponds to one concretewidth + height + fourcc + frameintervalcombination.
void uvc_host_free_formats(struct uvc_format **fmts);#
Release the array returned by uvc_host_get_formats().
void uvc_host_free_formats(struct uvc_format **fmts);
Raw-Format Conversion Helpers#
Besides direct frame access, three helper conversion APIs are provided:
int uvc_host_raw_to_nv12(const struct uvc_frame *frame, void *dst, size_t dst_len);
int uvc_host_raw_to_rgb565(const struct uvc_frame *frame, void *dst, size_t dst_len);
int uvc_host_raw_to_yuyv(const struct uvc_frame *frame, void *dst, size_t dst_len);
These helpers:
do not need an extra
struct uvc_formatuse the format negotiated by the most recent
uvc_host_init()apply only to raw pixel formats, not to
MJPEG
uvc_host_raw_to_nv12#
Supported input formats:
YUY2UYVYNV12I420
Required destination buffer size:
dst_len >= width * height * 3 / 2
Notes:
NV12 -> NV12is a direct copy path.If
dst == frame->userptrand the current format is alreadyNV12, the helper does not duplicate the copy.
uvc_host_raw_to_rgb565#
Supported input formats:
YUY2UYVY
Required destination buffer size:
dst_len >= width * height * 2
uvc_host_raw_to_yuyv#
Supported input formats:
YUY2UYVY
Required destination buffer size:
dst_len >= width * height * 2
Notes:
YUY2is already in YUYV byte order.If the current format is
YUY2anddst == frame->userptr, the helper avoids a duplicate copy.If the current format is
UYVY, the helper converts it to YUYV order.
Basic Usage Flow#
The typical call order is:
Initialize VB.
Optionally call
uvc_host_get_devinfo()oruvc_host_get_formats().Call
uvc_host_init().Call
uvc_host_start_stream().Repeatedly call
uvc_host_get_frame()anduvc_host_put_frame().Call
uvc_host_exit()before exit.
Example 1: Write MJPEG Data to a File#
struct uvc_format fmt = {
.width = 640,
.height = 480,
.fourcc = USBH_VIDEO_FOURCC_MJPEG,
.frameinterval = 10000000 / 30,
};
struct uvc_frame frame;
kd_mpi_vb_set_config(&config);
kd_mpi_vb_init();
if (uvc_host_init(&fmt) != 0) {
return -1;
}
if (uvc_host_start_stream() != 0) {
uvc_host_exit();
return -1;
}
if (uvc_host_get_frame(&frame, 3000) == 0) {
FILE *file = fopen("/sdcard/test.jpg", "wb");
if (file) {
fwrite(frame.userptr, 1, frame.bytesused, file);
fclose(file);
}
uvc_host_put_frame(&frame);
}
uvc_host_exit();
Example 2: Convert Raw Format to NV12 and Send It to VO#
struct uvc_format fmt = {
.width = 640,
.height = 480,
.fourcc = USBH_VIDEO_FOURCC_YUY2,
.frameinterval = 10000000 / 30,
};
struct uvc_frame frame;
if (uvc_host_init(&fmt) != 0) {
return -1;
}
if (uvc_host_start_stream() != 0) {
uvc_host_exit();
return -1;
}
while (uvc_host_get_frame(&frame, 5000) == 0) {
if (uvc_host_raw_to_nv12(&frame, vo_vaddr, vo_size) == 0) {
kd_mpi_vo_insert_frame(K_VO_LAYER_VIDEO1, &vf_info);
}
uvc_host_put_frame(&frame);
}
uvc_host_exit();
Sample Program#
The current host-side sample is:
src/rtsmart/examples/mpp/sample_uvc_host/uvc_test.c
Command line:
Usage: ./sample_uvc_host [connector_type] [rotation] [fourcc] [width] [height] [total_frame]
Parameter description:
Parameter |
Description |
|---|---|
|
Display type enum value |
|
Whether to rotate, |
|
|
|
Target width |
|
Target height |
|
Number of frames to process |
Run examples:
/sdcard/app/examples/mpp/sample_uvc_host.elf 20 1 MJPEG 640 480 1000000
/sdcard/app/examples/mpp/sample_uvc_host.elf 20 1 YUY2 640 480 1000000
Notes:
The program prints both the input
fourccand the final negotiatedfourcc.The
MJPEGpath uses VDEC internally before display.The non-
MJPEGpath converts the raw frame throughuvc_host_raw_to_nv12()and then sends it toVO.The sample periodically prints FPS.
Get connector_type#
Use:
list_connector
Configuration Options#
Notes#
Every successful
uvc_host_get_frame()must be paired withuvc_host_put_frame().userptrmust not be saved or reused afteruvc_host_put_frame().If you only need device info or format enumeration, you can call
uvc_host_get_devinfo()oruvc_host_get_formats()without callinguvc_host_init()first.For the
VOdisplay path, converting the raw format toNV12first is the more common approach.It is not recommended to keep a UVC camera and other long-running high-bandwidth bulk devices on the same USB hub, because USB bandwidth may become insufficient.
