Skip to content

Commit 65151b9

Browse files
committed
feat(class/video/usbd_video): add usbd_video_stream_start_write api for video split tranfer, every transfer with one ep_mps
1 parent 05315b7 commit 65151b9

File tree

3 files changed

+89
-28
lines changed

3 files changed

+89
-28
lines changed

class/video/usbd_video.c

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ struct usbd_video_priv {
1818
uint8_t power_mode;
1919
uint8_t error_code;
2020
struct video_entity_info info[3];
21+
uint8_t *ep_buffer;
22+
uint8_t *stream_buf;
23+
uint32_t stream_len;
24+
uint32_t stream_offset;
2125
} g_usbd_video[CONFIG_USBDEV_MAX_BUS];
2226

2327
static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
@@ -671,7 +675,7 @@ static int video_class_interface_request_handler(uint8_t busid, struct usb_setup
671675
} else {
672676
return usbd_video_control_unit_terminal_request_handler(busid, setup, data, len); /* Unit and Terminal Requests */
673677
}
674-
} else if (intf_num == 1) { /* Video Stream Inteface */
678+
} else if (intf_num == 1) { /* Video Stream Inteface */
675679
return usbd_video_stream_request_handler(busid, setup, data, len); /* Interface Stream Requests */
676680
}
677681
return -1;
@@ -700,7 +704,7 @@ static void video_notify_handler(uint8_t busid, uint8_t event, void *arg)
700704
}
701705
}
702706

703-
void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
707+
static void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
704708
{
705709
g_usbd_video[busid].probe.hintUnion.bmHint = 0x01;
706710
g_usbd_video[busid].probe.hintUnion1.bmHint = 0;
@@ -739,7 +743,8 @@ void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameIn
739743
g_usbd_video[busid].commit.bMaxVersion = 0;
740744
}
741745

742-
struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface *intf,
746+
struct usbd_interface *usbd_video_init_intf(uint8_t busid,
747+
struct usbd_interface *intf,
743748
uint32_t dwFrameInterval,
744749
uint32_t dwMaxVideoFrameSize,
745750
uint32_t dwMaxPayloadTransferSize)
@@ -763,14 +768,64 @@ struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface
763768
return intf;
764769
}
765770

771+
bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep)
772+
{
773+
struct video_payload_header *header = (struct video_payload_header *)g_usbd_video[busid].ep_buffer;
774+
uint32_t remain;
775+
uint32_t len;
776+
777+
remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
778+
779+
if (remain == 0) {
780+
return true;
781+
}
782+
783+
header->bHeaderLength = 2;
784+
header->headerInfoUnion.headerInfoBits.endOfHeader = 1;
785+
786+
len = MIN(remain, g_usbd_video[busid].probe.dwMaxPayloadTransferSize - header->bHeaderLength);
787+
memcpy(&g_usbd_video[busid].ep_buffer[header->bHeaderLength],
788+
&g_usbd_video[busid].stream_buf[g_usbd_video[busid].stream_offset],
789+
len);
790+
791+
g_usbd_video[busid].stream_offset += len;
792+
793+
if (g_usbd_video[busid].stream_offset == g_usbd_video[busid].stream_len) {
794+
header->headerInfoUnion.headerInfoBits.endOfFrame = 1;
795+
}
796+
797+
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buffer, len + header->bHeaderLength);
798+
return false;
799+
}
800+
801+
int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buffer, uint8_t *buf, uint32_t len)
802+
{
803+
if (usb_device_is_configured(busid) == 0) {
804+
return -1;
805+
}
806+
807+
g_usbd_video[busid].ep_buffer = ep_buffer;
808+
g_usbd_video[busid].stream_buf = buf;
809+
g_usbd_video[busid].stream_len = len;
810+
g_usbd_video[busid].stream_offset = 0;
811+
812+
struct video_payload_header *header = (struct video_payload_header *)g_usbd_video[busid].ep_buffer;
813+
814+
header->headerInfoUnion.headerInfoBits.frameIdentifier ^= 1;
815+
header->headerInfoUnion.headerInfoBits.endOfFrame = 0;
816+
817+
usbd_video_stream_split_transfer(busid, ep);
818+
return 0;
819+
}
820+
766821
uint32_t usbd_video_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
767822
{
768823
uint32_t packets;
769824
uint32_t last_packet_size;
770825
uint32_t picture_pos = 0;
771826
static uint8_t uvc_header[2] = { 0x02, 0x80 };
772827

773-
packets = (input_len + (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2) ) / (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
828+
packets = (input_len + (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2)) / (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
774829
last_packet_size = input_len - ((packets - 1) * (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2));
775830

776831
for (size_t i = 0; i < packets; i++) {

class/video/usbd_video.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface
2020

2121
void usbd_video_open(uint8_t busid, uint8_t intf);
2222
void usbd_video_close(uint8_t busid, uint8_t intf);
23+
24+
bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep);
25+
int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buffer, uint8_t *buf, uint32_t len);
26+
2327
uint32_t usbd_video_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
2428

2529
#ifdef __cplusplus

demo/video_static_mjpeg_template.c

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include "usbd_video.h"
88
#include "cherryusb_mjpeg.h"
99

10+
#define VIDEO_STREAM_SPLIT_ENABLE 1
11+
1012
#define VIDEO_IN_EP 0x81
1113
#define VIDEO_INT_EP 0x83
1214

@@ -34,7 +36,7 @@
3436
#define MAX_BIT_RATE (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS)
3537
#define MAX_FRAME_SIZE (unsigned long)(WIDTH * HEIGHT * 2)
3638

37-
#define VS_HEADER_SIZ (unsigned int)(VIDEO_SIZEOF_VS_INPUT_HEADER_DESC(1,1) + VIDEO_SIZEOF_VS_FORMAT_MJPEG_DESC + VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(1))
39+
#define VS_HEADER_SIZ (unsigned int)(VIDEO_SIZEOF_VS_INPUT_HEADER_DESC(1, 1) + VIDEO_SIZEOF_VS_FORMAT_MJPEG_DESC + VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC(1))
3840

3941
#define USB_VIDEO_DESC_SIZ (unsigned long)(9 + \
4042
VIDEO_VC_NOEP_DESCRIPTOR_LEN + \
@@ -180,8 +182,14 @@ void usbd_video_close(uint8_t busid, uint8_t intf)
180182

181183
void usbd_video_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
182184
{
183-
//USB_LOG_RAW("actual in len:%d\r\n", nbytes);
185+
#if VIDEO_STREAM_SPLIT_ENABLE
186+
if (usbd_video_stream_split_transfer(busid, ep)) {
187+
/* one frame has done */
188+
iso_tx_busy = false;
189+
}
190+
#else
184191
iso_tx_busy = false;
192+
#endif
185193
}
186194

187195
static struct usbd_endpoint video_in_ep = {
@@ -202,45 +210,39 @@ void video_init(uint8_t busid, uintptr_t reg_base)
202210
usbd_initialize(busid, reg_base, usbd_event_handler);
203211
}
204212

213+
#if VIDEO_STREAM_SPLIT_ENABLE
214+
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[MAX_PAYLOAD_SIZE];
215+
#else
205216
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[40 * 1024];
217+
#endif
206218

207219
void video_test(uint8_t busid)
208220
{
209221
uint32_t out_len;
210222
uint32_t packets;
211223

212224
(void)packets;
213-
memset(packet_buffer, 0, 40 * 1024);
225+
(void)out_len;
226+
memset(packet_buffer, 0, sizeof(packet_buffer));
227+
214228
while (1) {
215229
if (tx_flag) {
216-
packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg), packet_buffer, &out_len);
217-
#if 1
230+
#if VIDEO_STREAM_SPLIT_ENABLE
218231
iso_tx_busy = true;
219-
usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len);
232+
usbd_video_stream_start_write(busid, VIDEO_IN_EP, packet_buffer, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg));
220233
while (iso_tx_busy) {
221234
if (tx_flag == 0) {
222235
break;
223236
}
224237
}
225238
#else
226-
/* dwc2 must use this method */
227-
for (uint32_t i = 0; i < packets; i++) {
228-
if (i == (packets - 1)) {
229-
iso_tx_busy = true;
230-
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
231-
while (iso_tx_busy) {
232-
if (tx_flag == 0) {
233-
break;
234-
}
235-
}
236-
} else {
237-
iso_tx_busy = true;
238-
usbd_ep_start_write(busid, VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
239-
while (iso_tx_busy) {
240-
if (tx_flag == 0) {
241-
break;
242-
}
243-
}
239+
packets = usbd_video_payload_fill(busid, (uint8_t *)cherryusb_mjpeg, sizeof(cherryusb_mjpeg), packet_buffer, &out_len);
240+
241+
iso_tx_busy = true;
242+
usbd_ep_start_write(busid, VIDEO_IN_EP, packet_buffer, out_len);
243+
while (iso_tx_busy) {
244+
if (tx_flag == 0) {
245+
break;
244246
}
245247
}
246248
#endif

0 commit comments

Comments
 (0)