ipfs.io is the public gateway ran by Protocol Labs staff. There are dozens of other available gateways (we used like 8 gateways total before, and we decided to stick to the most performant ones). We still use infura.io for the videos too.
We have our own gateway that we use for pictures (snap1.d.tube).
Long term we plan to get rid of these gateways, by using js-ipfs in our player. Works, but not really stable as of my last try (memory leaks that cause the tab to crash after X minutes). With js-ipfs (native javascript IPFS node), we can load files directly from all nodes that have the file pinned, without going through gateways.
Also if you run ipfs locally and use the localhost:8080 gateway, then it's also going full p2p.
That's just the http gateway so that those of us who are stuck in the stone age can view stuff on ipfs. All that content is still available as long as someone has the content pinned somewhere.
By that definition I can't really think of many truly decentralized protocols. At some point you have to find an entry point into the "mesh", it's a chicken-and-egg problem. I believe that bitcoin seeds nodes IPs using the DNS system for instance (IIRC it used IRC before that), bittorrent uses torrent websites to share torrents/magnet links etc...
Once you've managed to connect to a node you can usually explore the topology of the network and find other peers so you only need the centralized resource temporarily to bootstrap new nodes. I'm not too familiar with IPFS but I imagine it works in a similar way.
Yeah, "Bootstrapping" a distributed network requires some sort of entrypoint. There are a couple of solutions, I'll share what IPFS is using.
First we have mDNS for local discovery. When you start a IPFS node, it starts announcing it's addresses over the local network. So this solution is pretty decentralized, as it'll connect with any node it can find. This doesn't work over the backbone though.
Secondly, we (Protocol Labs) run a couple of "bootstrap" nodes. They are normal IPFS nodes, but they run behind DNS and a static IP. Then in the standard distribution of IPFS Core (go-ipfs and js-ipfs) we hardcode the addresses. So when you start your node, it connects to the bootstrap nodes, which then shares which nodes they are connected with, so everyone ends up connected. This ends up introducing a bit of centralization, but because they are normal IPFS nodes, the community could agree to also connect to other bootstrap nodes, the only thing needed is a static address (optional really, but "Good to have") and a IPFS node running there.
Lastly, we have Signalling servers for webrtc and websocket connections (mainly for js-ipfs in the browser). This basically acts as a centralized endpoint for nodes to find each other. This is probably the most centralized solution to the bootstrapping problem.