0

我正在尝试将视频文件流式传输到 MCU,但每当它在设备上播放视频时,它的卡顿程度都非常适中。如果我在流媒体时使用我的电脑,情况会变得更糟。

例如,如果我正在流式传输,然后我滚动浏览聊天记录,比如 Discord,口吃变得非常非常糟糕,这非常奇怪,但可能是找到问题根源的关键因素。

注意:我们必须以 512 字节块流式传输 2352 字节(这是针对我正在流式传输的 ISO9660 光盘视频格式,对正在播放它的系统至关重要,因此不要认为这是问题或错误)。

这是我当前的代码实现。

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

关于为什么会发生这种情况的任何建议?我们libusbk在 Windows 7(32 位)下用作驱动程序。

任何帮助将不胜感激。

4

0 回答 0