Skip to content

Add basic rateless codec support - #102

Open
joe-calderon-ditto wants to merge 9 commits into
USNavalResearchLaboratory:masterfrom
joe-calderon-ditto:rateless
Open

Add basic rateless codec support#102
joe-calderon-ditto wants to merge 9 commits into
USNavalResearchLaboratory:masterfrom
joe-calderon-ditto:rateless

Conversation

@joe-calderon-ditto

@joe-calderon-ditto joe-calderon-ditto commented Jun 18, 2026

Copy link
Copy Markdown

Hello,

This PR adds basic support for a rateless codec, working toward the RaptorQ / non-systematic codec support discussed in #7.

What's included

  • A new rateless codec path through the encoder/segment layers, with the necessary message and session plumbing to carry it. A new underspecified scheme was added because I was unsure if rateless feel under the umbrella of small block codes, and I didn't know if using 6 would conflate general rateless codes to RaptorQ.
  • API additions in normApi.h / normApi.cpp to enable and configure it.
  • An examples/normRatelessTest.cpp example demonstrating the feature.

Notes

  • This is an initial, "basic" implementation intended as a starting point rather than a complete solution — feedback on the approach would be appreciated.
  • I'd be happy to adjust naming, API shape, or integration points to better match how you'd like rateless/non-systematic codecs to be handled in NORM.
  • I added NormTelemetry so rateless encoders could implement their own rate control for both proactive and reactive parity using metrics provided by norm.

If the interface looks ok, I can follow this pr with an actual implementation of a rateless codec.

@joe-calderon-ditto
joe-calderon-ditto marked this pull request as ready for review June 18, 2026 21:29
@joe-calderon-ditto joe-calderon-ditto changed the title Add basic rateless (RaptorQ) codec support Add basic rateless codec support Jun 18, 2026
@bebopagogo

bebopagogo commented Jul 2, 2026 via email

Copy link
Copy Markdown
Collaborator

@bebopagogo

Copy link
Copy Markdown
Collaborator

I've been looking through the changes you made and overall it looks like it's pretty much on the right track. So - great job on figuring that stuff out as the logic of my code is definitely not obvious with a lot of cruft from it's development history as research code to get the protocol operation sorted out. I do have a couple of initial questions/comments:

  1. I notice you have the Encoder/Decoder factory list and instances attached to the NormSession object. It could make sense to have those be part of the NormSessionMgr object? This isn't really critical, but in the case of a NormSessionMgr (corresponds to the NORM API instance) managing multiple sessions, there would only need to be a single 'factory' for each registered FEC codec.

  2. In the NormSession::SenderHandleNackMessage() method where you added code to process the NormRepairRequest::ERASURES repair request form, I think your added code ends up causing NormBlock::TxUpdate() to set "pending_mask" so that "numErasures" of parity packets are marked for transmission and assuming that for rateless codes they are always generating "fresh" (innovative) parity packets that should be OK. This makes use of the current NormBlock implementation that was designed for block codes so that not a lot of code change is needed. It seems it could be possible to update NormBlock to allow for representation of rateless code in without needing to use the bitmasks (i.e. no need to manage the parity bitmask on the sender side if they are a "don't care" for rateless codes), but probably the approach you took here makes best sense for initial implementation and further refinement of the NormBlock class definition could be a later refinement. No real question here other than to confirm that I understand what you implemented here?

  3. Also not really a question, but I do think it would be useful to expand your MockRatelessEncoder to something that could support testing of the basic rateless support code you have added. For example, it could just select random source symbols from the block to transmit as virtual "parity" packets. This would of course be a horribly inefficient 'rateless' code as it would take multiple NACK rounds or a lot of "auto parity" to randomly transmit the correct source symbols to make the receiver(s) happy (i.e. to be able to decode the block/object being transmitted). But if small-ish objects were used for testing with modest packet loss, it could validate the logic of the code you have added. I may try to do this if you don't have time or interest in doing that in lieu of having an actual code to test for the moment since I don't think it would difficult (just a little hash function or something to select unique random segments in the range of [0, ndata-1] and use those a surrogate for actual rateless code parity packets. I just can't guarantee how quickly I can get around to that, but wanted to run that idea by you?

  4. Finally, did you have a specific RaptorQ implementation in mind? It looks like "nanorq" might be a good candidate for the NORM code base as a native C/C++ implementation?

@joe-calderon-ditto

joe-calderon-ditto commented Jul 13, 2026

Copy link
Copy Markdown
Author

Thanks for taking the time to look through this. I will address (1) and (3) in a follow up commit. You are 100% spot on (2) we can leave as a future refinement. For (4), I'm obviously biased towards nanorq, I recently added a lightweight core interface that would work well with norm, but I'm concerned about complicating the build system too much. I planned to take a closer look at integration approaches after we hashed this pr out.

@joe-calderon-ditto

Copy link
Copy Markdown
Author

(1) and (3) are addressed. I realized decode() handling needed more care because rateless (unlike mds) codes can fail even with k symbols.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants