diff --git a/class/video/usb_video.h b/class/video/usb_video.h index bb81190d..4997526b 100644 --- a/class/video/usb_video.h +++ b/class/video/usb_video.h @@ -696,8 +696,8 @@ #define VIDEO_SET_CUR_EU_ERROR_RESILIENCY_CONTROL 0x0194U #endif -/*! @brief The payload header structure for MJPEG payload format. */ -struct video_mjpeg_payload_header { +/*! @brief The payload header structure. */ +struct video_payload_header { uint8_t bHeaderLength; /*!< The payload header length. */ union { uint8_t bmheaderInfo; /*!< The payload header bitmap field. */ @@ -1118,7 +1118,7 @@ struct video_autoexposure_mode { 0x00, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \ 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) */ \ 0x0d + PP_NARG(__VA_ARGS__), \ 0x24, \ @@ -1131,7 +1131,7 @@ struct video_autoexposure_mode { 0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \ 0x00, /* bTriggerSupport : Hardware trigger supported for 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.*/ #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(dwMaxBitRate), /* dwMaxBitRate (4bytes): Max bit rate in bits/s */ \ 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 */ \ __VA_ARGS__ // clang-format on diff --git a/class/video/usbd_video.c b/class/video/usbd_video.c index a21f324c..fbb2beec 100644 --- a/class/video/usbd_video.c +++ b/class/video/usbd_video.c @@ -24,8 +24,6 @@ struct usbd_video_cfg_priv { .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) { 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); } else { 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 last_packet_size; uint32_t picture_pos = 0; + static uint8_t uvc_header[2] = { 0x02, 0x80 }; packets = input_len / usbd_video_cfg.probe.dwMaxPayloadTransferSize + 1; last_packet_size = input_len - ((packets - 1) * (usbd_video_cfg.probe.dwMaxPayloadTransferSize - 2)) + 2; for (size_t i = 0; i < packets; i++) { - output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i] = 0x02; - output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] = head_toggle; + output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i] = uvc_header[0]; + output[usbd_video_cfg.probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1]; if (i == (packets - 1)) { 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 { 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; } } - head_toggle ^= 1; + uvc_header[1] ^=1; *out_len = (input_len + 2 * 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; - } -} +} \ No newline at end of file diff --git a/class/video/usbd_video.h b/class/video/usbd_video.h index f7ed4008..cbb54d71 100644 --- a/class/video/usbd_video.h +++ b/class/video/usbd_video.h @@ -20,7 +20,6 @@ struct usbd_interface *usbd_video_alloc_intf(uint32_t dwFrameInterval, void usbd_video_open(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); -void usbd_video_mjpeg_payload_header_toggle(uint8_t *output, uint32_t packets); #ifdef __cplusplus } diff --git a/demo/video_static_mjpeg_template.c b/demo/video_static_mjpeg_template.c index 77360fff..685b01da 100644 --- a/demo/video_static_mjpeg_template.c +++ b/demo/video_static_mjpeg_template.c @@ -15,7 +15,7 @@ // #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 3)) | (0x02 << 11)) #else -#define MAX_PAYLOAD_SIZE 1023 +#define MAX_PAYLOAD_SIZE 1020 #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11)) #endif @@ -38,12 +38,12 @@ 9 + \ 14 + \ 11 + \ - 38 + \ + 30 + \ 9 + \ 7) #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_PID 0xffff @@ -51,13 +51,13 @@ #define USBD_LANGID_STRING 1033 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), VIDEO_VC_DESCRIPTOR_INIT(0x00, 0, 0x0100, VC_TERMINAL_SIZ, 48000000, 0x02), 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_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), /* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */ 0x07, /* bLength */ @@ -175,8 +175,8 @@ static struct usbd_endpoint video_in_ep = { void video_init() { 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(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(INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE)); usbd_add_endpoint(&video_in_ep); usbd_initialize(); @@ -188,15 +188,17 @@ void video_test() { uint32_t out_len; uint32_t packets; + memset(packet_buffer, 0, 10 * 1024); while (1) { if (tx_flag) { 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; usbd_ep_start_write(VIDEO_IN_EP, packet_buffer, out_len); while (iso_tx_busy) { } #else + /* dwc2 must use this method */ for (uint32_t i = 0; i < packets; i++) { if (i == (packets - 1)) { iso_tx_busy = true;