(self, data)
return bytes(encoded_data)
Encode message into FEC packets encompassing multiple FEC objects

        Generate the FEC packets (chunk + metadata) for the given message. If
        the message exceeds the capacity of one FEC object (up to 256 chunks),
        generate multiple FEC objects.

        Args:
            data : Data to encode (bytes array)

        Returns:
            Bytes array with all FEC packets serially (concatenated).
Encode message into FEC packets encompassing multiple FEC objects
Encode message into FEC packets encompassing multiple FEC objects
def encode(self, data):
        """Encode message into FEC packets encompassing multiple FEC objects

        Generate the FEC packets (chunk + metadata) for the given message. If
        the message exceeds the capacity of one FEC object (up to 256 chunks),
        generate multiple FEC objects.

        Args:
            data : Data to encode (bytes array)

        Returns:
            Bytes array with all FEC packets serially (concatenated).

        """
        assert (isinstance(data, bytes))

        # The FEC object should contain up to 256 chunks, including the
        # original (systematic) and the overhead chunks. The original data
        # object (to be encoded) should occupy up to "256/(1 + overhead)"
        # chunks, whereas the overhead chunks should occupy "(overhead *
        # 256)/(1 + overhead)" chunks. Also, the overhead cannot be greater
        # than 255, otherwise the original data has zero chunks per object.
        assert(self.overhead <= MAX_OVERHEAD), \
            "FEC overhead exceeds the maximum of {}".format(MAX_OVERHEAD)

        max_obj_size = floor(MAX_FEC_CHUNKS / (1 + self.overhead)) * CHUNK_SIZE
        n_fec_objects = ceil(len(data) / max_obj_size)

        logger.debug("Message Size: {} / FEC Objects: {}".format(
            len(data), n_fec_objects))

        # Generate the FEC packets from (potentially) multiple FEC objects
        fec_pkts = []
        for i_obj in range(n_fec_objects):
            s_byte = i_obj * max_obj_size  # starting byte
            e_byte = (i_obj + 1) * max_obj_size  # ending byte
            fec_object = data[s_byte:e_byte]

            logger.debug("FEC Object: {}".format(i_obj))

            fec_chunks = self._encode_obj(fec_object)

            # FEC packets
            for i_chunk, chunk in enumerate(fec_chunks):
                metadata = struct.pack(HEADER_FORMAT, i_obj, n_fec_objects,
                                       i_chunk, len(fec_object))
                fec_pkts.append(metadata + chunk)

        # Concatenate all FEC packets to form a single encoded data
        # array. Concatenate them in random order so that the chunks from the
        # same object are not sent consecutively. This strategy is useful to
        # avoid error bursts.
        encoded_data = bytearray()
        random.shuffle(fec_pkts)
        for fec_pkt in fec_pkts:
            encoded_data += fec_pkt

        assert (len(encoded_data) % PKT_SIZE == 0)

        return bytes(encoded_data)
def encode ( self , data ) : assert ( isinstance ( data , bytes ) ) # The FEC object should contain up to 256 chunks, including the # original (systematic) and the overhead chunks. The original data # object (to be encoded) should occupy up to "256/(1 + overhead)" # chunks, whereas the overhead chunks should occupy "(overhead * # 256)/(1 + overhead)" chunks. Also, the overhead cannot be greater # than 255, otherwise the original data has zero chunks per object. assert ( self . overhead <= MAX_OVERHEAD ) , "FEC overhead exceeds the maximum of {}" . format ( MAX_OVERHEAD ) max_obj_size = floor ( MAX_FEC_CHUNKS / ( 1 + self . overhead ) ) * CHUNK_SIZE n_fec_objects = ceil ( len ( data ) / max_obj_size ) logger . debug ( "Message Size: {} / FEC Objects: {}" . format ( len ( data ) , n_fec_objects ) ) # Generate the FEC packets from (potentially) multiple FEC objects fec_pkts = [ ] for i_obj in range ( n_fec_objects ) : s_byte = i_obj * max_obj_size # starting byte e_byte = ( i_obj + 1 ) * max_obj_size # ending byte fec_object = data [ s_byte : e_byte ] logger . debug ( "FEC Object: {}" . format ( i_obj ) ) fec_chunks = self . _encode_obj ( fec_object ) # FEC packets for i_chunk , chunk in enumerate ( fec_chunks ) : metadata = struct . pack ( HEADER_FORMAT , i_obj , n_fec_objects , i_chunk , len ( fec_object ) ) fec_pkts . append ( metadata + chunk ) # Concatenate all FEC packets to form a single encoded data # array. Concatenate them in random order so that the chunks from the # same object are not sent consecutively. This strategy is useful to # avoid error bursts. encoded_data = bytearray ( ) random . shuffle ( fec_pkts ) for fec_pkt in fec_pkts : encoded_data += fec_pkt assert ( len ( encoded_data ) % PKT_SIZE == 0 ) return bytes ( encoded_data )