Exemplo n.º 1
0
    def onNewRow(self, row, generator):
        u"""
        Called by self=FecGenerator when a new row FEC packet is generated and available for output.

        Send the encapsulated row FEC packet.

        :param row: Generated row FEC packet
        :type row: FecPacket
        :param generator: The generator that fired this method / event
        :type generator: FecGenerator
        """
        row_rtp = RtpPacket.create(row.sequence, 0, RtpPacket.MP2T_PT, row.bytes)
        log.info('Send ROW FEC packet seq=%s snbase=%s LxD=%sx%s trec=%s socket=%s' %
                 (row.sequence, row.snbase, row.L, row.D, row.timestamp_recovery, self.col_socket))
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
        sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
        sock.sendto(row_rtp.bytes, (self.row_socket['ip'], self.row_socket['port']))
Exemplo n.º 2
0
    def onNewCol(self, col, generator):
        u"""
        Called by self=FecGenerator when a new column FEC packet is generated and available for output.

        Send the encapsulated column FEC packet.

        :param col: Generated column FEC packet
        :type col: FecPacket
        :param generator: The generator that fired this method / event
        :type generator: FecGenerator
        """
        col_rtp = RtpPacket.create(col.sequence, 0, RtpPacket.MP2T_PT, col.bytes)
        log.info('Send COL FEC packet seq=%s snbase=%s LxD=%sx%s trec=%s socket=%s' %
                 (col.sequence, col.snbase, col.L, col.D, col.timestamp_recovery, self.col_socket))
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
        sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
        sock.sendto(col_rtp.bytes, (self.col_socket['ip'], self.col_socket['port']))
Exemplo n.º 3
0
    def onNewRow(self, row, generator):
        u"""
        Called by self=FecGenerator when a new row FEC packet is generated and available for output.

        Send the encapsulated row FEC packet.

        :param row: Generated row FEC packet
        :type row: FecPacket
        :param generator: The generator that fired this method / event
        :type generator: FecGenerator
        """
        row_rtp = RtpPacket.create(row.sequence, 0, RtpPacket.MP2T_PT,
                                   row.bytes)
        log.info(
            'Send ROW FEC packet seq=%s snbase=%s LxD=%sx%s trec=%s socket=%s'
            % (row.sequence, row.snbase, row.L, row.D, row.timestamp_recovery,
               self.col_socket))
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
                             socket.IPPROTO_UDP)
        sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
        sock.sendto(row_rtp.bytes,
                    (self.row_socket['ip'], self.row_socket['port']))
Exemplo n.º 4
0
    def onNewCol(self, col, generator):
        u"""
        Called by self=FecGenerator when a new column FEC packet is generated and available for output.

        Send the encapsulated column FEC packet.

        :param col: Generated column FEC packet
        :type col: FecPacket
        :param generator: The generator that fired this method / event
        :type generator: FecGenerator
        """
        col_rtp = RtpPacket.create(col.sequence, 0, RtpPacket.MP2T_PT,
                                   col.bytes)
        log.info(
            'Send COL FEC packet seq=%s snbase=%s LxD=%sx%s trec=%s socket=%s'
            % (col.sequence, col.snbase, col.L, col.D, col.timestamp_recovery,
               self.col_socket))
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
                             socket.IPPROTO_UDP)
        sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
        sock.sendto(col_rtp.bytes,
                    (self.col_socket['ip'], self.col_socket['port']))
Exemplo n.º 5
0
    def recoverMediaPacket(self, media_sequence, cross, fec):
        u"""
        Recover a missing media packet helped by a FEC packet, this method is also called to
        register an incoming media packet if it is registered as missing.
        """
        recovered_by_fec = not fec is None

        # Read and remove "cross" it from the buffer
        col_sequence = cross['col_sequence']
        row_sequence = cross['row_sequence']
        del self.crosses[media_sequence]

        # Recover the missing media packet and remove any useless linked fec packet
        if recovered_by_fec:
            if len(fec.missing) != 1:
                raise NotImplementedError(FecReceiver.ER_MISSING_COUNT % len(fec.missing))
            if fec.direction == FecPacket.COL and fec.sequence != col_sequence:
                raise NotImplementedError(FecReceiver.ER_COL_MISMATCH % (fec.sequence, col_sequence))
            if fec.direction == FecPacket.ROW and fec.sequence != row_sequence:
                raise NotImplementedError(FecReceiver.ER_ROW_MISMATCH % (fec.sequence, row_sequence))

            # Media packet recovery
            # > Copy fec packet fields into the media packet
            media = RtpPacket.create(media_sequence, fec.timestamp_recovery,
                                     fec.payload_type_recovery, fec.payload_recovery)
            payload_size = fec.length_recovery

            # > recovered payload ^= all media packets linked to the fec packet
            aborted = False
            media_max = (fec.snbase + fec.na * fec.offset) & RtpPacket.S_MASK
            media_test = fec.snbase
            while media_test != media_max:
                if media_test == media_sequence:
                    media_test = (media_test + fec.offset) & RtpPacket.S_MASK
                    continue
                friend = self.medias[media_test]
                # Unable to recover the media packet if any of the friend media packets is missing
                if not friend:
                    self.media_aborted_recovery += 1
                    aborted = True
                    break
                media.payload_type ^= friend.payload_type
                media.timestamp ^= friend.timestamp
                payload_size ^= friend.payload_size
                # FIXME FIXME FIXME FIXME FIXME OPTIMIZATION FIXME FIXME FIXME FIXME
                for no in range(min(len(media.payload), len(friend.payload))):
                    media.payload[no] ^= friend.payload[no]
                media_test = (media_test + fec.offset) & RtpPacket.S_MASK

            # If the media packet is successfully recovered
            if not aborted:
                media.payload = media.payload[0:payload_size]
                self.media_recovered += 1
                if media.sequence in self.medias:
                    self.media_overwritten += 1
                self.medias[media.sequence] = media
                if len(self.medias) > self.max_media:
                    self.max_media = len(self.medias)
                if fec.direction == FecPacket.COL:
                    del self.cols[fec.sequence]
                else:
                    del self.rows[fec.sequence]

        # Check if a cascade effect happens ...
        fec_col = self.cols.get(col_sequence) if col_sequence else None
        fec_row = self.rows.get(row_sequence) if row_sequence else None

        if fec_col:
            fec_col.setRecovered(media_sequence)
        if fec_row:
            fec_row.setRecovered(media_sequence)

        if fec_col:
            if len(fec_col.missing) == 1:
                # Cascade !
                cascade_media_sequence = fec_col.missing[0]
                if cascade_media_sequence:
                    cascade_cross = self.crosses.get(cascade_media_sequence)
                    if cascade_cross:
                        self.recoverMediaPacket(cascade_media_sequence, cascade_cross, fec_col)
                    else:
                        raise NotImplementedError(
                            'recoverMediaPacket(%s, %s, %s):\n%s\nmedia sequence : %s\n%s\n' %
                            (media_sequence, cross, fec, FecReceiver.ER_NULL_COL_CASCADE,
                             cascade_media_sequence, fec_col))
                else:
                    raise NotImplementedError(FecReceiver.ER_GET_COL_CASCADE % fec_col)

        if fec_row:
            if len(fec_row.missing) == 1:
                # Cascade !
                cascade_media_sequence = fec_row.missing[0]
                if cascade_media_sequence:
                    cascade_cross = self.crosses.get(cascade_media_sequence)
                    if cascade_cross:
                        self.recoverMediaPacket(cascade_media_sequence, cascade_cross, fec_row)
                    else:
                        raise NotImplementedError(
                            '%s\nrecoverMediaPacket(%s, %s, %s):\nmedia sequence : %s\n%s\n' %
                            (FecReceiver.ER_NULL_ROW_CASCADE, media_sequence, cross, fec,
                             cascade_media_sequence, fec_row))
                else:
                    raise NotImplementedError(FecReceiver.ER_GET_ROW_CASCADE % fec_row)
Exemplo n.º 6
0
    def recoverMediaPacket(self, media_sequence, cross, fec):
        u"""
        Recover a missing media packet helped by a FEC packet, this method is also called to
        register an incoming media packet if it is registered as missing.
        """
        recovered_by_fec = not fec is None

        # Read and remove "cross" it from the buffer
        col_sequence = cross['col_sequence']
        row_sequence = cross['row_sequence']
        del self.crosses[media_sequence]

        # Recover the missing media packet and remove any useless linked fec packet
        if recovered_by_fec:
            if len(fec.missing) != 1:
                raise NotImplementedError(FecReceiver.ER_MISSING_COUNT %
                                          len(fec.missing))
            if fec.direction == FecPacket.COL and fec.sequence != col_sequence:
                raise NotImplementedError(FecReceiver.ER_COL_MISMATCH %
                                          (fec.sequence, col_sequence))
            if fec.direction == FecPacket.ROW and fec.sequence != row_sequence:
                raise NotImplementedError(FecReceiver.ER_ROW_MISMATCH %
                                          (fec.sequence, row_sequence))

            # Media packet recovery
            # > Copy fec packet fields into the media packet
            media = RtpPacket.create(media_sequence, fec.timestamp_recovery,
                                     fec.payload_type_recovery,
                                     fec.payload_recovery)
            payload_size = fec.length_recovery

            # > recovered payload ^= all media packets linked to the fec packet
            aborted = False
            media_max = (fec.snbase + fec.na * fec.offset) & RtpPacket.S_MASK
            media_test = fec.snbase
            while media_test != media_max:
                if media_test == media_sequence:
                    media_test = (media_test + fec.offset) & RtpPacket.S_MASK
                    continue
                friend = self.medias[media_test]
                # Unable to recover the media packet if any of the friend media packets is missing
                if not friend:
                    self.media_aborted_recovery += 1
                    aborted = True
                    break
                media.payload_type ^= friend.payload_type
                media.timestamp ^= friend.timestamp
                payload_size ^= friend.payload_size
                # FIXME FIXME FIXME FIXME FIXME OPTIMIZATION FIXME FIXME FIXME FIXME
                for no in range(min(len(media.payload), len(friend.payload))):
                    media.payload[no] ^= friend.payload[no]
                media_test = (media_test + fec.offset) & RtpPacket.S_MASK

            # If the media packet is successfully recovered
            if not aborted:
                media.payload = media.payload[0:payload_size]
                self.media_recovered += 1
                if media.sequence in self.medias:
                    self.media_overwritten += 1
                self.medias[media.sequence] = media
                if len(self.medias) > self.max_media:
                    self.max_media = len(self.medias)
                if fec.direction == FecPacket.COL:
                    del self.cols[fec.sequence]
                else:
                    del self.rows[fec.sequence]

        # Check if a cascade effect happens ...
        fec_col = self.cols.get(col_sequence) if col_sequence else None
        fec_row = self.rows.get(row_sequence) if row_sequence else None

        if fec_col:
            fec_col.setRecovered(media_sequence)
        if fec_row:
            fec_row.setRecovered(media_sequence)

        if fec_col:
            if len(fec_col.missing) == 1:
                # Cascade !
                cascade_media_sequence = fec_col.missing[0]
                if cascade_media_sequence:
                    cascade_cross = self.crosses.get(cascade_media_sequence)
                    if cascade_cross:
                        self.recoverMediaPacket(cascade_media_sequence,
                                                cascade_cross, fec_col)
                    else:
                        raise NotImplementedError(
                            'recoverMediaPacket(%s, %s, %s):\n%s\nmedia sequence : %s\n%s\n'
                            % (media_sequence, cross, fec,
                               FecReceiver.ER_NULL_COL_CASCADE,
                               cascade_media_sequence, fec_col))
                else:
                    raise NotImplementedError(FecReceiver.ER_GET_COL_CASCADE %
                                              fec_col)

        if fec_row:
            if len(fec_row.missing) == 1:
                # Cascade !
                cascade_media_sequence = fec_row.missing[0]
                if cascade_media_sequence:
                    cascade_cross = self.crosses.get(cascade_media_sequence)
                    if cascade_cross:
                        self.recoverMediaPacket(cascade_media_sequence,
                                                cascade_cross, fec_row)
                    else:
                        raise NotImplementedError(
                            '%s\nrecoverMediaPacket(%s, %s, %s):\nmedia sequence : %s\n%s\n'
                            % (FecReceiver.ER_NULL_ROW_CASCADE, media_sequence,
                               cross, fec, cascade_media_sequence, fec_row))
                else:
                    raise NotImplementedError(FecReceiver.ER_GET_ROW_CASCADE %
                                              fec_row)