예제 #1
0
class Packer:
    """
    专门用于数据打包
    """
    def __init__(self):
        #压缩参数,后面cv2.imencode将会用到,对于jpeg来说,15代表图像质量,越高代表图像质量越好为 0-100,默认95
        self.encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 80]

        self.init_config()
        # 这里的队列,用于多线程压缩图片之后,放入队列
        # Python的队列是线程安全的
        self.Q = Queue()

    def init_config(self):
        config = Config()
        # 初始化相机信息
        self.w = w = int(config.get("camera", "w"))
        self.h = h = int(config.get("camera", "h"))
        self.d = d = int(config.get("camera", "d"))
        self.frame_pieces = frame_pieces = int(config.get("camera", "pieces"))
        self.frame_size = w * h
        self.frame_size_3d = w * h * d
        self.piece_size = int(w * h * d / frame_pieces)
        self.idx_frame = int(h / self.frame_pieces)  # 一块数据,在原始图像占多少行

        # 初始化打包头信息
        self.head_name = config.get("header", "name")
        self.head_data_len_len = int(config.get("header", "data"))
        self.head_index_len = int(config.get("header", "index"))
        self.head_time_len = int(config.get("header", "time"))
        self.img_len = int(config.get("header", "data_size"))
        self.pack_len = int(config.get("header", "total_size"))
        # 当前的设计下,head_len=16
        self.head_len = len(
            self.head_name
        ) + self.head_data_len_len + self.head_index_len + self.head_time_len
        # self.pack_len = self.head_len + self.piece_size # 46096

        # 初始化队列大小信息
        self.queue_size = int(config.get("receive", "queue_size"))
        self.frame_limit = int(config.get("receive", "frame_limit"))
        self.piece_limit = int(config.get("receive", "piece_limit"))

        self.queue_size = int(config.get("send", "queue_size"))
        self.send_piece_limit = int(config.get("send", "piece_limit"))
        self.send_piece_min = int(config.get("send", "piece_min"))

    def pack_data(self, index, create_time, data, Q):
        """
        Pack data over udp
        """
        if len(data) == 0:
            return None
        # intialize compress thread
        thread = Thread(target=self.compress,
                        args=(index, create_time, data, Q))
        thread.daemon = True
        thread.start()

        # pack = None
        # while pack is None:
        #     pack = self.read_compress()

        # return pack

    def read_compress(self):
        # print(self.Q.qsize()) # 单机运行的时候,queue的长度持续增大
        # 拥塞控制(这里可以用个算法,时间限制就写简单点)
        frame = self.Q.get()
        # if self.Q.qsize() > self.queue_size*0.5:
        #     self.Q = Queue()
        #     if self.Q.mutex:
        #         self.Q.queue.clear()
        return frame

    def compress(self, idx, create_time, frame_raw, Q):
        if len(frame_raw) == 0: return
        row_start = idx * self.idx_frame
        row_end = (idx + 1) * self.idx_frame
        try:
            result, imgencode = cv2.imencode('.jpg',
                                             frame_raw[row_start:row_end],
                                             self.encode_param)
        except:
            return
        if result:
            imgbytes = imgencode.tobytes()
            data_len = len(imgbytes)
            res = self.pack_header(data_len, idx, create_time)

            # 写入图像数据,需要padding
            # pad_bytes = b'\0' * (self.img_len - data_len)
            res += imgbytes
            # res += pad_bytes
            Q.append(res)
        return 1

    def unpack_data(self, res):
        data_len = 0
        index = -1
        create_time = 0
        data = b''
        if len(res) < self.head_len:
            return index, create_time, data
        head_block = res[:self.head_len]
        name, data_len, index, create_time = self.unpack_header(head_block)
        data_end = data_len + self.head_len
        body_block = res[self.head_len:data_end]

        return index, create_time, body_block

    def pack_header(self, data_len, index, create_time):
        res = b''
        res += self.head_name.encode()
        res += data_len.to_bytes(self.head_data_len_len, byteorder="big")
        res += index.to_bytes(self.head_index_len, byteorder="big")
        res += create_time.to_bytes(self.head_time_len, byteorder="big")
        return res

    def unpack_header(self, head_block):
        name = head_block[:4]
        data_len = int.from_bytes(head_block[4:8], byteorder='big')
        index = int.from_bytes(head_block[8:9], byteorder='big')
        create_time = int.from_bytes(head_block[9:self.head_len],
                                     byteorder='big')
        return name, data_len, index, create_time