update video template
This commit is contained in:
@@ -696,8 +696,8 @@
|
|||||||
#define VIDEO_SET_CUR_EU_ERROR_RESILIENCY_CONTROL 0x0194U
|
#define VIDEO_SET_CUR_EU_ERROR_RESILIENCY_CONTROL 0x0194U
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*! @brief The payload header structure for MJPEG payload format. */
|
/*! @brief The payload header structure. */
|
||||||
struct video_mjpeg_payload_header {
|
struct video_payload_header {
|
||||||
uint8_t bHeaderLength; /*!< The payload header length. */
|
uint8_t bHeaderLength; /*!< The payload header length. */
|
||||||
union {
|
union {
|
||||||
uint8_t bmheaderInfo; /*!< The payload header bitmap field. */
|
uint8_t bmheaderInfo; /*!< The payload header bitmap field. */
|
||||||
@@ -1118,7 +1118,7 @@ struct video_autoexposure_mode {
|
|||||||
0x00, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
|
0x00, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \
|
||||||
0x00 /* iInterface : unused */
|
0x00 /* iInterface : unused */
|
||||||
|
|
||||||
#define VIDEO_VS_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress, bControlSize, ...) \
|
#define VIDEO_VS_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress, ...) \
|
||||||
/*Class-specific VideoStream Header Descriptor (Input) */ \
|
/*Class-specific VideoStream Header Descriptor (Input) */ \
|
||||||
0x0d + PP_NARG(__VA_ARGS__), \
|
0x0d + PP_NARG(__VA_ARGS__), \
|
||||||
0x24, \
|
0x24, \
|
||||||
@@ -1131,7 +1131,7 @@ struct video_autoexposure_mode {
|
|||||||
0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \
|
0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \
|
||||||
0x00, /* bTriggerSupport : Hardware trigger supported for still image capture */ \
|
0x00, /* bTriggerSupport : Hardware trigger supported for still image capture */ \
|
||||||
0x00, /* bTriggerUsage : Hardware trigger should initiate a still image capture. */ \
|
0x00, /* bTriggerUsage : Hardware trigger should initiate a still image capture. */ \
|
||||||
bControlSize, /* bControlSize : Size of the bmaControls field */ \
|
PP_NARG(__VA_ARGS__), /* bControlSize : Size of the bmaControls field */ \
|
||||||
__VA_ARGS__ /* bmaControls : No VideoStreaming specific controls are supported.*/
|
__VA_ARGS__ /* bmaControls : No VideoStreaming specific controls are supported.*/
|
||||||
|
|
||||||
#define VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors, GUIDFormat) \
|
#define VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_INIT(bFormatIndex, bNumFrameDescriptors, GUIDFormat) \
|
||||||
@@ -1191,7 +1191,7 @@ struct video_autoexposure_mode {
|
|||||||
DBVAL(dwMinBitRate), /* dwMinBitRate (4bytes): Min bit rate in bits/s */ \
|
DBVAL(dwMinBitRate), /* dwMinBitRate (4bytes): Min bit rate in bits/s */ \
|
||||||
DBVAL(dwMaxBitRate), /* dwMaxBitRate (4bytes): Max bit rate in bits/s */ \
|
DBVAL(dwMaxBitRate), /* dwMaxBitRate (4bytes): Max bit rate in bits/s */ \
|
||||||
DBVAL(dwMaxVideoFrameBufferSize), /* dwMaxVideoFrameBufSize (4bytes): Maximum video or still frame size, in bytes. */ \
|
DBVAL(dwMaxVideoFrameBufferSize), /* dwMaxVideoFrameBufSize (4bytes): Maximum video or still frame size, in bytes. */ \
|
||||||
DBVAL(dwDefaultFrameInterval), /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \
|
dwDefaultFrameInterval, /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \
|
||||||
bFrameIntervalType, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \
|
bFrameIntervalType, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \
|
||||||
__VA_ARGS__
|
__VA_ARGS__
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ struct usbd_video_cfg_priv {
|
|||||||
.info[2] = { .bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, .bEntityId = 0x02, .wTerminalType = 0x00 },
|
.info[2] = { .bDescriptorSubtype = VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, .bEntityId = 0x02, .wTerminalType = 0x00 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool head_toggle = false;
|
|
||||||
|
|
||||||
static int usbd_video_control_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
static int usbd_video_control_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||||
{
|
{
|
||||||
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
||||||
@@ -696,7 +694,6 @@ static void video_notify_handler(uint8_t event, void *arg)
|
|||||||
usbd_video_open(intf->bInterfaceNumber);
|
usbd_video_open(intf->bInterfaceNumber);
|
||||||
} else {
|
} else {
|
||||||
usbd_video_close(intf->bInterfaceNumber);
|
usbd_video_close(intf->bInterfaceNumber);
|
||||||
head_toggle = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -767,28 +764,23 @@ uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8
|
|||||||
uint32_t packets;
|
uint32_t packets;
|
||||||
uint32_t last_packet_size;
|
uint32_t last_packet_size;
|
||||||
uint32_t picture_pos = 0;
|
uint32_t picture_pos = 0;
|
||||||
|
static uint8_t uvc_header[2] = { 0x02, 0x80 };
|
||||||
|
|
||||||
packets = input_len / usbd_video_cfg.probe.dwMaxPayloadTransferSize + 1;
|
packets = input_len / usbd_video_cfg.probe.dwMaxPayloadTransferSize + 1;
|
||||||
last_packet_size = input_len - ((packets - 1) * (usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2)) + 2;
|
last_packet_size = input_len - ((packets - 1) * (usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2)) + 2;
|
||||||
|
|
||||||
for (size_t i = 0; i < packets; i++) {
|
for (size_t i = 0; i < packets; i++) {
|
||||||
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i] = 0x02;
|
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
|
||||||
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] = head_toggle;
|
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
|
||||||
if (i == (packets - 1)) {
|
if (i == (packets - 1)) {
|
||||||
memcpy(&output[2 + usbd_video_cfg.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size - 2);
|
memcpy(&output[2 + usbd_video_cfg.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size - 2);
|
||||||
|
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
|
||||||
} else {
|
} else {
|
||||||
memcpy(&output[2 + usbd_video_cfg.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2);
|
memcpy(&output[2 + usbd_video_cfg.probe.dwMaxPayloadTransferSize * i], &input[picture_pos], usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2);
|
||||||
picture_pos += usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2;
|
picture_pos += usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
head_toggle ^= 1;
|
uvc_header[1] ^=1;
|
||||||
*out_len = (input_len + 2 * packets);
|
*out_len = (input_len + 2 * packets);
|
||||||
return packets;
|
return packets;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbd_video_mjpeg_payload_header_toggle(uint8_t *output, uint32_t packets)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < packets; i++) {
|
|
||||||
output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] ^= 0x01;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,6 @@ struct usbd_interface *usbd_video_alloc_intf(uint32_t dwFrameInterval,
|
|||||||
void usbd_video_open(uint8_t intf);
|
void usbd_video_open(uint8_t intf);
|
||||||
void usbd_video_close(uint8_t intf);
|
void usbd_video_close(uint8_t intf);
|
||||||
uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
|
uint32_t usbd_video_mjpeg_payload_fill(uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
|
||||||
void usbd_video_mjpeg_payload_header_toggle(uint8_t *output, uint32_t packets);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
// #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 3)) | (0x02 << 11))
|
// #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 3)) | (0x02 << 11))
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define MAX_PAYLOAD_SIZE 1023
|
#define MAX_PAYLOAD_SIZE 1020
|
||||||
#define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11))
|
#define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -38,12 +38,12 @@
|
|||||||
9 + \
|
9 + \
|
||||||
14 + \
|
14 + \
|
||||||
11 + \
|
11 + \
|
||||||
38 + \
|
30 + \
|
||||||
9 + \
|
9 + \
|
||||||
7)
|
7)
|
||||||
|
|
||||||
#define VC_TERMINAL_SIZ (unsigned int)(13 + 18 + 12 + 9)
|
#define VC_TERMINAL_SIZ (unsigned int)(13 + 18 + 12 + 9)
|
||||||
#define VS_HEADER_SIZ (unsigned int)(13 + 1 + 11 + 38)
|
#define VS_HEADER_SIZ (unsigned int)(13 + 1 + 11 + 30)
|
||||||
|
|
||||||
#define USBD_VID 0xffff
|
#define USBD_VID 0xffff
|
||||||
#define USBD_PID 0xffff
|
#define USBD_PID 0xffff
|
||||||
@@ -51,13 +51,13 @@
|
|||||||
#define USBD_LANGID_STRING 1033
|
#define USBD_LANGID_STRING 1033
|
||||||
|
|
||||||
const uint8_t video_descriptor[] = {
|
const uint8_t video_descriptor[] = {
|
||||||
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
|
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
|
||||||
USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
|
||||||
VIDEO_VC_DESCRIPTOR_INIT(0x00, 0, 0x0100, VC_TERMINAL_SIZ, 48000000, 0x02),
|
VIDEO_VC_DESCRIPTOR_INIT(0x00, 0, 0x0100, VC_TERMINAL_SIZ, 48000000, 0x02),
|
||||||
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
|
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
|
||||||
VIDEO_VS_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 1, 0x00),
|
VIDEO_VS_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 0x00),
|
||||||
VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(0x01, 0x01),
|
VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(0x01, 0x01),
|
||||||
VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, MAX_FRAME_SIZE, INTERVAL, 0x00, DBVAL(INTERVAL), DBVAL(INTERVAL), DBVAL(0)),
|
VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, MAX_FRAME_SIZE, DBVAL(INTERVAL), 0x01, DBVAL(INTERVAL)),
|
||||||
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
|
VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
|
||||||
/* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
|
/* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
|
||||||
0x07, /* bLength */
|
0x07, /* bLength */
|
||||||
@@ -175,8 +175,8 @@ static struct usbd_endpoint video_in_ep = {
|
|||||||
void video_init()
|
void video_init()
|
||||||
{
|
{
|
||||||
usbd_desc_register(video_descriptor);
|
usbd_desc_register(video_descriptor);
|
||||||
usbd_add_interface(usbd_video_alloc_intf(CAM_FPS, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
usbd_add_interface(usbd_video_alloc_intf(INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||||
usbd_add_interface(usbd_video_alloc_intf(CAM_FPS, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
usbd_add_interface(usbd_video_alloc_intf(INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
|
||||||
usbd_add_endpoint(&video_in_ep);
|
usbd_add_endpoint(&video_in_ep);
|
||||||
|
|
||||||
usbd_initialize();
|
usbd_initialize();
|
||||||
@@ -188,15 +188,17 @@ void video_test()
|
|||||||
{
|
{
|
||||||
uint32_t out_len;
|
uint32_t out_len;
|
||||||
uint32_t packets;
|
uint32_t packets;
|
||||||
|
memset(packet_buffer, 0, 10 * 1024);
|
||||||
while (1) {
|
while (1) {
|
||||||
if (tx_flag) {
|
if (tx_flag) {
|
||||||
packets = usbd_video_mjpeg_payload_fill((uint8_t *)jpeg_data, sizeof(jpeg_data), packet_buffer, &out_len);
|
packets = usbd_video_mjpeg_payload_fill((uint8_t *)jpeg_data, sizeof(jpeg_data), packet_buffer, &out_len);
|
||||||
#if 1
|
#if 0
|
||||||
iso_tx_busy = true;
|
iso_tx_busy = true;
|
||||||
usbd_ep_start_write(VIDEO_IN_EP, packet_buffer, out_len);
|
usbd_ep_start_write(VIDEO_IN_EP, packet_buffer, out_len);
|
||||||
while (iso_tx_busy) {
|
while (iso_tx_busy) {
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
/* dwc2 must use this method */
|
||||||
for (uint32_t i = 0; i < packets; i++) {
|
for (uint32_t i = 0; i < packets; i++) {
|
||||||
if (i == (packets - 1)) {
|
if (i == (packets - 1)) {
|
||||||
iso_tx_busy = true;
|
iso_tx_busy = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user