- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Webcam provides only isochronous endpoint for data transferring. Bulk is not supported as we know.
Therefore it looks quite obivious that the USB 2.0 host firmware which deals with webcam as a device should open its endpoint as isochronous. A question on this was dealt in the following thread.
In an effort to receive webcam MJPEG stream in my host firmware, I'm facing a problem which I can't reasonably explain.
- Test environment
For experiment, I defined macro "BULK" which turns on the setting for bulk transfer and on the other case(When BULK is not defined), isochronous is activated.- - Endpoint and DMA channel is created as below (see endpoint.c)
- - MJPEG stream is received by UvcRecvThread function (see UvcRecvThread.c)
- Test Results
- - isochronous case (when "BULK" is not defined), the full log can be found in "iso.txt".
- - bulk case, the full log is "bulk.txt"
Question
- I thought that the host firmware must use isochronous endpoint because webcam only supports isochronous endpoint. But as we see in the above test, it was also possible to receive data through bulk as well.
- Though I could receive data both in isochronous and bulk mode, there were significant difference between them.
The MJPEG stream is a series of jpegs. A jpeg image starts with SOI(Start of Image, 0xffd8) and ends with EOI(End of Image, 0xffd9). When I searched for the iso.txt, I could find only 1 SOI while 211 EOIs. This means I lost quite a lot of SOIs except the very first one. In contrast, in bulk.txt, I could find 115 SOIs and 127 EOIs.
I think that isochronous endpoint is the right choice but the result is not what I expected. In isochronous case, the result shows I'm missing many important data from the webcam. - Bulk test case seems quite promising regardless if it is a right one or not. In my long term test, after few hours of running, the thread gets stuck.
Regards,
Rossi
Solved! Go to Solution.
- Labels:
-
USB Superspeed Peripherals
- Tags:
- uvc
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
As the issue seems to be due to bandwidth, you can try requesting more data (in multiples of 3072(max packet size)) from the USB host side (FX3) so that packets do not get dropped.
Also, can you try alternate setting with lower bandwidth to check if with lower bandwidth the packets are dropped?
Rashi
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
endpoint.c (Endpoint and DMA setup)
glHostUvcEp = 0x81;
size = 1024;
/* Initialize the UVC */
CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof(epCfg));
#ifdef BULK
//Bulk
epCfg.type = CY_U3P_USB_EP_BULK;
epCfg.mult = 1;
epCfg.pollingRate = 1;
#else
//Isochronous
epCfg.type = CY_U3P_USB_EP_ISO;
epCfg.mult = 3;
epCfg.pollingRate = 0;
#endif
epCfg.maxPktSize = size;
/* Since DMA buffer sizes can only be multiple of 16 bytes and
* also since this is an interrupt endpoint where the max data
* packet size is same as the maxPktSize field, the fullPktSize
* has to be a multiple of 16 bytes. */
size = ((size + 0x0F) & ~0x0F);
epCfg.fullPktSize = size;
epCfg.isStreamMode = CyFalse;
status = CyU3PUsbHostEpAdd (glHostUvcEp, &epCfg);
if (status != CY_U3P_SUCCESS)
{
goto enum_error;
}
/* Create a DMA channel for this EP. */
CyU3PMemSet ((uint8_t *)&dmaCfg, 0, sizeof(dmaCfg));
dmaCfg.size = size;
dmaCfg.count = CY_FX_HOST_DMA_BUF_COUNT;
dmaCfg.prodSckId = (CyU3PDmaSocketId_t)(CY_U3P_UIB_SOCKET_PROD_0 + (0x0F & glHostUvcEp));
dmaCfg.consSckId = CY_U3P_CPU_SOCKET_CONS;
dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT;
dmaCfg.cb = NULL;
dmaCfg.prodHeader = 0;
dmaCfg.prodFooter = 0;
dmaCfg.consHeader = 0;
dmaCfg.prodAvailCount = 0;
status = CyU3PDmaChannelCreate (&glHostUvcCh, CY_U3P_DMA_TYPE_MANUAL_IN, &dmaCfg);
if (status != CY_U3P_SUCCESS)
{
goto app_error;
}
UvcRecvThread.c
void
UvcRecvThread(
uint32_t Value)
{
uint8_t buffer[1024*4];
CyU3PReturnStatus_t status;
CyU3PUsbHostEpStatus_t epStatus;
uint32_t prodXferCount = 0;
uint32_t consXferCount = 0;
CyU3PDmaState_t state = 0;
CyU3PDmaBuffer_t buf_p;
#ifdef BULK
//Bulk
uint16_t count = 1024;
#else
//Isochronous
uint16_t count = 3*1024;
#endif
CyU3PThreadSleep (3000);
CyU3PDebugPrint(4,"UvcRecvThread starts\r\n");
for (;;)
{
buf_p.buffer = buffer;
buf_p.count = 0;
buf_p.size = ((count + 0x0F) & ~0x0F);
buf_p.status = 0;
CyU3PDebugPrint(4,"CyU3PDmaChannelSetupRecvBuffer...\r\n");
status = CyU3PDmaChannelSetupRecvBuffer (&glHostUvcCh, &buf_p);
CyU3PDebugPrint(4,"CyU3PDmaChannelSetupRecvBuffer status=0x%x,size=%d\r\n",status,buf_p.size);
if(status!=CY_U3P_SUCCESS) continue;
CyU3PDebugPrint(4,"CyU3PUsbHostEpSetXfer(%d)...\r\n",count);
status = CyU3PUsbHostEpSetXfer (glHostUvcEp,CY_U3P_USB_HOST_EPXFER_NORMAL, count);
CyU3PDebugPrint(4,"CyU3PUsbHostEpSetXfer status=0x%x,count=%d\r\n",status,count);
if(status!=CY_U3P_SUCCESS) continue;
CyU3PDebugPrint(4,"CyU3PUsbHostEpWaitForCompletion...\r\n");
status = CyU3PUsbHostEpWaitForCompletion (glHostUvcEp, &epStatus, 10);
CyU3PDebugPrint(4,"CyU3PUsbHostEpWaitForCompletion status=0x%x,ep=0x%x,epStatus=0x%x\r\n",status,glHostUvcEp,epStatus);
CyU3PDebugPrint(4,"CyU3PDmaChannelWaitForCompletion...\r\n");
status = CyU3PDmaChannelWaitForCompletion (&glHostUvcCh, CYU3P_NO_WAIT);
CyU3PDebugPrint(4,"CyU3PDmaChannelWaitForCompletion status=0x%x\r\n",status);
if(status!=CY_U3P_SUCCESS) continue;
status = CyU3PDmaChannelGetStatus (&glHostUvcCh, &state, &prodXferCount, &consXferCount);
CyU3PDebugPrint (4,"CyU3PDmaChannelGetStatus status=0x%x state=0x%x length=%d\r\n",status,state,prodXferCount);
for(uint32_t i=0;i<prodXferCount-1;i++) {
if(buffer[i]==0xff && buffer[i+1]==0xd8) CyU3PDebugPrint(4, "SOI\r\n");
if(buffer[i]==0xff && buffer[i+1]==0xd9) CyU3PDebugPrint(4, "EOI\r\n");
}
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
As you might be aware that isochronous transfers do not guarantee the delivery of data, the loss could be due to packet drop.
Please let us know the bandwidth of the video that you are streaming to FX3 (USB 2.0 Host).
Also, can you please try increasing "count" value to 6144 bytes (x2 3072)
Rashi
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Rashi
This is the endpoint descripor information of my webcam.
From the above, I'm using Interace1, bAlternateSetting=6.
As your recommendation, I'm testing with count value of 6144 bytes. The initial test results look quite promising! The host can now catch SOIs unlike before.
I'll be back after the long term test over night.
Thank you
Regards,
Rossi
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
As the issue seems to be due to bandwidth, you can try requesting more data (in multiples of 3072(max packet size)) from the USB host side (FX3) so that packets do not get dropped.
Also, can you try alternate setting with lower bandwidth to check if with lower bandwidth the packets are dropped?
Rashi
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Rashi,
The test during the weekend was successfully ended. As expected, I could observe SOI,EOI data from the stream. So, it's reasonable to say the cause of the missing data is the bandwidth as you pointed out.
Thank you for your help.
Regards,
Rossi