Re: Zero Packets in Isochronous Transfer Reception

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jul 10, 2018 at 9:23 AM, Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote:
> On Mon, 9 Jul 2018, R0b0t1 wrote:
>
>>
>> Is anyone able to comment on this in more detail? I thought it was
>> supposed to be reported if a transfer did not arrive in time.
>
> It depends on what you mean by "arrive in time".  If driver on the host
> waits too long before submitting an URB, nothing special is reported.
> For example, suppose URB X is submitted and is scheduled for frame 732.
> After URB X completes, URB X+1 is submitted.  But it may already be too
> late to schedule X+1 in frame 733; in that case it could simply be
> assigned to some later frame with no error indication.  (Or the
> submission may fail, or the URB may complete almost immediately with a
> -EXDEV status error; it depends on details of the timing.)
>
> On the other hand, if an URB is assigned to some particular frame and
> the device does not send a reply packet at the right time during that
> frame, the URB will complete with its iso_frame_desc[] status set to
> -EXDEV.
>

I see. I expected this but was not checking error conditions properly.
Thank you for the explanation.

>>
>> I updated my C code and now everything works. I think the issue was GC
>> pauses in Python.
>
> That could easily cause problems, given the way your program worked.
>
>> What does not work: multiple transfers within an isochronous packet.
>> More than ~3 transfers results in missing packets (using libusb from
>> C).
>
> If you're still submitting just one transfer at a time, the same
> phenomenon (GC pauses?) could still cause missing packets.
>

GC stands for garbage collection. The Python libusb wrapper I was
using would constantly allocate buffer objects that would need to be
collected. A fix would probably involve using numpy objects instead,
if I cared, but that would be fairly invasive.

>> There is no easy way to implement multiple concurrent transfers with
>> PyUSB. I may implement it in my C code, but the time between transfers
>> is relatively large and I see no issues currently.
>
> All right, if you say so.  The time between frames (for a full-speed
> device, typical of audio) is one millisecond.  That may seem relatively
> large to you, but in some settings it is considered rather tight.
>
> And in fact, the timing window could be a lot shorter than 1 ms.  An
> URB scheduled for frame 732 won't complete until after frame 733 has
> started.  And in order to be scheduled during frame 733, an URB must be
> submitted not long after the start of that frame -- and certainly
> before its end.
>

I implemented your recommendation and I still have issues receiving
multiple isochronous packets as part of one scheduled transfer. The
maximum is now 5 or 6 in a row, as opposed to 2 or 3. Any more and
there is stuttering. It does not matter how deep I make the transfer
ring buffer. There are different effects based on how many isochronous
packets I schedule at once (slight buzzing, lots of buzzing, ear-bleed
inducing buzzing).

This may be okay as I can still get it working. However I was hoping
to test the throughput and latency of receiving a few hundred
milliseconds of audio at one time as opposed to constant smaller
transfers. Windows prefers the former, I'd like to know if there is
any reason why. (It probably related to the kernel's structure and
irrelevant when on other OSes - I get consistently better throughput
on Linux without trying.)

I also expect operation to proceed smoothly no matter how many
transfers are scheduled. If I am double (or triple, or more) buffering
packet scheduling what else could there be?

>>
>> Can you explain what you mean?
>
> The pipeline is the queue of URBs that have been submitted on the host
> and are waiting to complete.  Your program never has a queue length
> larger than 1, and at times the length drops to 0 (after one transfer
> completes and before the program submits the next transfer).
>
> If you submitted multiple transfers at the start, the queue length
> would be larger than 1 and it would be most unlikely ever to drop down
> to 0.  The kernel driver treats a queue length of 0 as special for
> scheduling purposes; to keep a smooth flow of packets with precisely
> one frame between adjacent entries, it is best to ensure that the queue
> length is always positive.
>

Thanks for the clarification. That is a pretty compelling reason to
keep a ring buffer. I was hoping to keep the code as simple as
possible. My program does actually manage to keep the transfer queued
before the device sends so I am still confused, especially since the
problem persists.

Cheers,
    R0b0t1.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux