tvkitchen / utilities

Standalone packages and tools used by appliances and implementations.
GNU Lesser General Public License v3.0
1 stars 1 forks source link

Mapping out the MpegTsDemuxer flow #6

Open slifty opened 3 years ago

slifty commented 3 years ago

Discussion

What do you want to talk about?

The MpegTsDemuxer logic is complicated, but I'd like to try to map it out a little in the spirit of understanding how it works right now. This issue will capture that exploration. Some of the discussion may end up winding up as documentation as well.

Relevant Research

slifty commented 3 years ago

The current MpegTsDemuxer API

The sole interaction point to the demuxer is MpegTsDemuxer. Here's how to interact with it...

That's basically the API -- in goes stream data, out comes packets. This is in some ways performing the same function as a transform stream, but it doesn't implement that API.

Action Items

slifty commented 3 years ago

How does processing work?

An MpegTsDemuxer instance tracks a few things as class properties:

A lot of these attributes are passed directly to utility functions WHICH MODIFY THEIR PROPERTIES.

This makes it really hard to know exactly what's going on / debug.

Action Items

slifty commented 3 years ago

How does processing work (continued)

When new data is processed it is passed a buffer (it can be passed some other stuff which makes it possible to specify what portion of the buffer to use, but at this point I think that just complicates the API. I would rather have the developer be responsible for passing exactly the data they want processed).

The processing then does the following:

  1. Calculate remainder -- this is how much remaining data in the leftover that needs to be merged with the new data.
const remainder = (PACKET_LEN - this.ptr) % PACKET_LEN
  1. I actually think the next step has a bug.
if (remainder > 0) {
    if (len < remainder) {
        this.leftover.set(buffer.subarray(offset, offset + len), this.ptr)
        return 1 // still have an incomplete packet
    }
    ...
}

What this is saying, as written, is:

If there was leftover data, and if the length of the new data is less than the length of the leftover data, then combine the leftover data and exit out.

But that's not what we want! For instance, if packet length is 100, the remainder from the last processing is 80, the new data is 70, then 80 + 70 = 150 which is greater than the packet length and we very well could have a complete packet.

What I believe it SHOULD be doing is saying is:

If the leftover data + the new data is less than the packet length then combine the leftover data and exit out because we can't possibly have a complete packet.

The current logic also doesn't update the internal pointer even though it adds data to leftover, which I think means that data would get overwritten. I've opened an upstream issue to get clarification.

Action Items

slifty commented 3 years ago

How does processing work (continued again)

  1. If there was no remainder then first we define a few things:
  1. Next, we iterate over the input buffer. This uses some tracking variables:

On each loop we do some things:

Action Items

slifty commented 3 years ago

Process has been refactored, but it would still be worth doing a deep dive into how the demuxPacket method works (and it's various spinoffs).