MCPcopy Create free account
hub / github.com/ClassicOldSong/Apollo / encode

Function encode

src/stream.cpp:649–725  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

647 };
648
649 static fec_t encode(const std::string_view &payload, size_t blocksize, size_t fecpercentage, size_t minparityshards, size_t prefixsize) {
650 auto payload_size = payload.size();
651
652 auto pad = payload_size % blocksize != 0;
653
654 auto aligned_data_shards = payload_size / blocksize;
655 auto data_shards = aligned_data_shards + (pad ? 1 : 0);
656 auto parity_shards = (data_shards * fecpercentage + 99) / 100;
657
658 // increase the FEC percentage for this frame if the parity shard minimum is not met
659 if (parity_shards < minparityshards && fecpercentage != 0) {
660 parity_shards = minparityshards;
661 fecpercentage = (100 * parity_shards) / data_shards;
662
663 BOOST_LOG(verbose) << "Increasing FEC percentage to "sv << fecpercentage << " to meet parity shard minimum"sv << std::endl;
664 }
665
666 auto nr_shards = data_shards + parity_shards;
667
668 // If we need to store a zero-padded data shard, allocate that first to
669 // to keep the shards in order and reduce buffer fragmentation
670 auto parity_shard_offset = pad ? 1 : 0;
671 util::buffer_t<char> shards {(parity_shard_offset + parity_shards) * blocksize};
672 util::buffer_t<uint8_t *> shards_p {nr_shards};
673 std::vector<platf::buffer_descriptor_t> payload_buffers;
674 payload_buffers.reserve(2);
675
676 // Point into the payload buffer for all except the final padded data shard
677 auto next = std::begin(payload);
678 for (auto x = 0; x < aligned_data_shards; ++x) {
679 shards_p[x] = (uint8_t *) next;
680 next += blocksize;
681 }
682 payload_buffers.emplace_back(std::begin(payload), aligned_data_shards * blocksize);
683
684 // If the last data shard needs to be zero-padded, we must use the shards buffer
685 if (pad) {
686 shards_p[aligned_data_shards] = (uint8_t *) &shards[0];
687
688 // GCC doesn't figure out that std::copy_n() can be replaced with memcpy() here
689 // and ends up compiling a horribly slow element-by-element copy loop, so we
690 // help it by using memcpy()/memset() directly.
691 auto copy_len = std::min<size_t>(blocksize, std::end(payload) - next);
692 std::memcpy(shards_p[aligned_data_shards], next, copy_len);
693 if (copy_len < blocksize) {
694 // Zero any additional space after the end of the payload
695 std::memset(shards_p[aligned_data_shards] + copy_len, 0, blocksize - copy_len);
696 }
697 }
698
699 // Add a payload buffer describing the shard buffer
700 payload_buffers.emplace_back(std::begin(shards), shards.size());
701
702 if (fecpercentage != 0) {
703 // Point into our allocated buffer for the parity shards
704 for (auto x = 0; x < parity_shards; ++x) {
705 shards_p[data_shards + x] = (uint8_t *) &shards[(parity_shard_offset + x) * blocksize];
706 }

Callers 1

videoBroadcastThreadFunction · 0.70

Calls 4

moveFunction · 0.85
sizeMethod · 0.45
getMethod · 0.45
beginMethod · 0.45

Tested by

no test coverage detected