RTOS UVC Host Usage Instructions#
Overview#
RT-Smart UVC Host user-space interface uses the uvc_host_* naming convention, and image formats are described using FOURCC.
Related example 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 are:
USBH_VIDEO_FOURCC_YUY2USBH_VIDEO_FOURCC_UYVYUSBH_VIDEO_FOURCC_NV12USBH_VIDEO_FOURCC_I420USBH_VIDEO_FOURCC_MJPEG
Where:
MJPEGis a compressed stream formatYUY2,UYVY,NV12,I420are raw pixel formats
Data Structures#
User-space header file: 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 |
|---|---|
|
Expected or negotiated image width |
|
Expected or negotiated image height |
|
Image format, using |
|
Frame interval, in units of 100ns; for example, 30fps can be written as |
Description:
uvc_host_init()uses it to receive user input, and also writes back the actual negotiated modeIf the user-specified resolution/frame rate cannot be fully matched, the underlying layer will return 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 |
|---|---|
|
The UVC buffer index corresponding to the current frame |
|
The actual valid data length of the current frame |
|
The user-space virtual address of the current frame |
|
Video frame information corresponding to the raw image |
|
VDEC input information corresponding to the MJPEG stream |
Description:
The user-space structure does not include internally used buffer mapping fields, such as
length,offset, etc.userptris only valid while the frame is held, and cannot be used after callinguvc_host_put_frame()For MJPEG, if you want to write directly to a file,
bytesusedis typically used
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 Introduction#
int uvc_host_init(struct uvc_format *fmt);#
Initialize the UVC Host device.
int uvc_host_init(struct uvc_format *fmt);
Description:
fmtinputs the user’s expectedwidth/height/fourcc/frameintervalAfter successful initialization,
fmtwill be updated to the actual negotiated modeThe current UVC buffer is managed uniformly by the underlying layer; it is recommended to complete VB initialization before use
Return value:
Returns
0on successReturns a negative value on failure
int uvc_host_start_stream(void);#
Start the UVC video stream.
int uvc_host_start_stream(void);
Return value:
Returns
0on successReturns a negative value on failure
int uvc_host_get_frame(struct uvc_frame *frame, unsigned int timeout_ms);#
Get one frame of UVC data.
int uvc_host_get_frame(struct uvc_frame *frame, unsigned int timeout_ms);
Description:
This interface will block until a frame of data is obtained or a timeout occurs
After success, the
framewill return buffer information anduserptrAfter each successful acquisition, a paired call to
uvc_host_put_frame()must be made
Return value:
Returns
0on successReturns a negative value on failure
int uvc_host_put_frame(struct uvc_frame *frame);#
Return a frame buffer.
int uvc_host_put_frame(struct uvc_frame *frame);
Description:
After returning, the buffer can be reused by the driver
After the call, the
userptrof the frame can no longer be used
void uvc_host_exit(void);#
Close the UVC device and release resources.
void uvc_host_exit(void);
Description:
If the stream has been started,
uvc_host_exit()will be responsible for performing stream-stop cleanupThere is currently no separate
uvc_host_stop_stream()provided
int uvc_host_get_devinfo(char *info, int len);#
Get device vendor/product information.
int uvc_host_get_devinfo(char *info, int len);
Description:
On success, it returns a string in the format
vendor#productEven if
uvc_host_init()has not been called yet, the interface will temporarily open the device for querying
int uvc_host_get_formats(struct uvc_format **fmts);#
Enumerate all modes supported by the device.
int uvc_host_get_formats(struct uvc_format **fmts);
Description:
The return value is the number of modes
*fmtsis allocated internally by the interface;uvc_host_free_formats()must be called after use is completeEach
uvc_formatcorresponds to a specificwidth + height + fourcc + frameinterval
void uvc_host_free_formats(struct uvc_format **fmts);#
Free the mode array returned by uvc_host_get_formats().
void uvc_host_free_formats(struct uvc_format **fmts);
Raw Format Conversion Helper Interfaces#
In addition to direct streaming, three commonly used raw format conversion interfaces are also 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);
Features of these interfaces:
No longer require passing in
struct uvc_formatadditionallyThey directly use the format negotiated by the most recent
uvc_host_init()Only applicable to raw pixel formats, not applicable to
MJPEG
uvc_host_raw_to_nv12#
Supported input formats:
YUY2UYVYNV12I420
Destination buffer size requirement:
dst_len >= width * height * 3 / 2
Notes:
NV12 -> NV12is a direct copyWhen
dst == frame->userptrand the current format is alreadyNV12, no duplicate copy will occur
uvc_host_raw_to_rgb565#
Supported input formats:
YUY2UYVY
Destination buffer size requirement:
dst_len >= width * height * 2
uvc_host_raw_to_yuyv#
Supported input formats:
YUY2UYVY
Destination buffer size requirement:
dst_len >= width * height * 2
Notes:
YUY2itself is YUYV byte orderWhen the current format is
YUY2anddst == frame->userptr, no duplicate copy will occurWhen the current format is
UYVY, it will be converted to YUYV arrangement
Basic Usage Flow#
The typical call sequence is as follows:
Initialize VB
Optional: call
uvc_host_get_devinfo()/uvc_host_get_formats()Call
uvc_host_init()Call
uvc_host_start_stream()Loop calling
uvc_host_get_frame()/uvc_host_put_frame()Call
uvc_host_exit()when the program ends
Example 1: Writing 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: Converting Raw Format to NV12 and Sending to VO for Display#
struct uvc_format fmt = {
.width = 640,
.height = 480,
.fourcc = USBH_VIDEO_FOURCC_YUY2,
.frameinterval = 10000000 / 30,
};
struct uvc_frame frame;
/* vo_vaddr / vo_size / vf_info are prepared in advance by the VO side */
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();
Example Program#
The current Host example is located at:
src/rtsmart/examples/mpp/sample_uvc_host/uvc_test.c
Command line arguments:
Usage: ./sample_uvc_host [connector_type] [rotation] [fourcc] [width] [height] [total_frame]
Parameter description:
Parameter |
Description |
|---|---|
|
Screen type enum value |
|
Whether to rotate, |
|
Supports |
|
Target width |
|
Target height |
|
Number of frames to process |
Running example:
/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 will print the input
fourccand the actual negotiatedfourccThe
MJPEGpath internally goes through VDEC decoding before displayNon-
MJPEGpaths will first calluvc_host_raw_to_nv12()and then send to VO for displayThe program will periodically print FPS
Getting connector_type#
You can view it with the following command:
msh />list_connector
Configuration Options#
Notes#
After
uvc_host_get_frame()succeeds, you must pair it with a call touvc_host_put_frame().userptrmust not be saved or used acrossuvc_host_put_frame().If you only need to enumerate formats or read device information, you can simply call
uvc_host_get_formats()/uvc_host_get_devinfo()without callinguvc_host_init()first.For the
VOdisplay path, it is currently more common to first convert the original format toNV12.It is not recommended to keep a UVC camera and high-bandwidth Bulk devices connected to the same Hub for extended periods, as you may encounter USB bandwidth shortage issues.
