What's the functional difference between fountain codes and polynomial secret sharing?
Consider what happens when we construct Shamir's secret sharing scheme for a secret $s$ and a reconstruction threshold $t=4$.  Our polynomial will be of degree $t - 1$ with $a_i$ being random coefficients:

$$
f(x) = s + a_1x + a_2x^2 + a_3x^3
$$

The shares for the $n$ players are given by $f(1), f(2), \dots f(n)$.  Any $t \ge 4$ of the players can reconstruct the polynomial $f(x)$ and can  recover the secret as $s = f(0)$, but any $t &lt; 4$ of the players do not have enough information and thus learn nothing about the secret $s$.

We can use this exact same technique as a fountain code through nothing more than a change in perspective.  Instead of a secret $s$, we have a message $m$:

$$
g(x) = m + a_1x + a_2x^2 + a_3x^3
$$

And instead of giving each player $n$ the share $f(n)$, we broadcast a series of blocks $g(1), g(2), \dots$ to the players.  Once a player has received $t \ge 4$ message blocks, they have enough information to reconstruct the polynomial $g(x)$ and can recover the original message as $m = g(0)$.  By choosing a large enough finite field, it is possible to generate a very large number of unique message blocks.

Practical fountain codes are usually based on low-density parity codes for reasons of efficiency, but I hope this example helps to show that in many ways error-correcting codes and secret-sharing schemes are merely two interpretations of the same underlying concept.