|
From: Matt <ma...@cy...> - 2021-07-08 18:34:11
|
Hi,
I am trying to stream a video file to a MCU, but whenever it plays the
video on the device it's stuttering pretty moderately. If I use my PC
whilst streaming, it gets considerably worse.
For example, if I am streaming and then I scroll through chat history in
say, Discord, the stuttering becomes much, much worse which is
incredibly strange, but may be a key factor in finding the root of the
problem.
NOTE: We must stream 2352 bytes in 512 byte chunks (this is for the
ISO9660 disc video format I am streaming and is critical to the system
that is playing it so do not think that this is the problem or error).
Here is my current code implementation.
// main streaming loop
// we send the data by 512 bytes, so 2352 fits into 5 x 512
// [0] code
// [1] sync_id
// [2] readsync_id
// [3, 4, 5, 6] cd_lba
int VideoStream(char *image_path)
{
#define BYTES_PER_SECTOR 2352
int error = 0; // the error returned from the LibUSB transfer functions
int received = 0;
int length = 0;
unsigned char curr_req_id = 0, req_id = 0;
unsigned char curr_rdsync_id = 0, rdsync_id = 0;
unsigned char wr_lock = 0;
unsigned char *pbuf;
int fread_result; // contains the result from 'fread'
unsigned char code;
unsigned int cd_lba, offset;
memset(cd_buffer, 0, CD_BUFFER_MAX_LEN); // clear the 'cd_buffer'
array before we use it
fp = fopen(image_path, "rb"); // open the video file (read mode)
if (fp == NULL)
{
#ifdef DEBUG
printf("Failed to open the video file \"%s\"\n", image_path);
#endif
return 0;
}
fseek(fp, 0L, SEEK_END);
// calculate the size of the file
size_t fsize = ftell(fp);
if (fsize <= 0) return 0;
fseek(fp, 0, SEEK_SET);
// clear the 'cd_buffer' array again
memset(cd_buffer, 0, CD_BUFFER_MAX_LEN);
// main streaming loop
while (1)
{
if(libusb_interrupt_transfer(handle, BULK_EP_IN, cd_buffer, 16,
&transferred, 3000) < 0)
{
StopUSBStream();
// these crash the program? why??
//libusb_close(handle);
//libusb_exit(NULL);
return 0;
}
code = cd_buffer[0];
curr_req_id = cd_buffer[1];
curr_rdsync_id = cd_buffer[2];
if (req_id == curr_req_id) continue;
req_id = curr_req_id;
if (code == 0x99)
{
// idle
}
else if (code == 0x01) // data request
{
if (wr_lock)
{
if (rdsync_id != curr_rdsync_id)
{
wr_lock = 0;
}
}
if (!wr_lock)
{
cd_lba = cd_buffer[3] + 0x0000100 * cd_buffer[4] +
0x0010000 * cd_buffer[5] + 0x1000000 * cd_buffer[6];
offset = (cd_lba - 150) * 0x930;
fseek(fp, 0, SEEK_SET);
fseek(fp, offset, SEEK_SET);
fread_result = fread(cd_buffer + 4, 1,
BYTES_PER_SECTOR, fp);
if (fread_result < BYTES_PER_SECTOR)
{
int rd_try = 10;
int rd_cmplt = 0;
int rd_more = BYTES_PER_SECTOR;
int rd_total = fread_result;
while (rd_try)
{
rd_more -= fread_result;
offset += fread_result;
fseek(fp, offset, SEEK_SET);
fread_result = fread(cd_buffer + 4, 1, rd_more,
fp);
rd_total += fread_result;
if (rd_total == BYTES_PER_SECTOR) rd_cmplt = 1;
// if we have read all the bytes, flag that the reading is completed
rd_try--; // negate 1 byte
}
// if reading is still not complete, flag that we
have an error
if (!rd_cmplt) rd_cmplt = 0;
}
pbuf = &cd_buffer[2];
int n = CD_BUFFER_MAX_LEN;
int c = 0;
int wrlen = 512;
while (n)
{
pbuf[0] = 2;
pbuf[1] = c;
error = libusb_bulk_transfer(handle, BULK_EP_OUT,
pbuf, wrlen, &transferred, 0);
pbuf += (wrlen-2);
n -= wrlen;
c++;
}
if (error == 0)
{
rdsync_id = curr_rdsync_id;
wr_lock = 1;
}
}
}
}
}
Any suggestions as per why this might be happening? We are using libusbk
as the driver under Windows 7 (32-bit).
Any help would be greatly appreciated.
On a side note, I have also tried using HIDSharp. I of course
uninstalled the libusbk driver and let Windows install its default
driver, but that uses interrupt endpoints as far as I understand which
in theory would be even worse than bulk. Turns out that theory is true
because it performed even worse than LibUSB. It would play ~500ms of
video on our device and thn stall for 3-5 seconds before repeating
again. I also had to patch the code to retry when the GetFeature event
would fail.
If anyone wants the code for the HIDSharp test, it can be found here:
https://community.atmel.com/forum/atmel-sam3u-hid-usb-streaming-stuttering
Mainly however, we are determined to stick with and use LibUSB, so any
advice on how to find and solve this issue would again be grealy
appreciated.
Regards,
Matt (Cybdyn Systems)
Embedded Systems Designer
|