update video template

This commit is contained in:
sakumisu
2022-10-05 17:16:56 +08:00
parent a50459755b
commit 3af227c879
4 changed files with 22 additions and 29 deletions

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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
} }

View File

@@ -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;