You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

153 lines
6.5 KiB

import cv2
import threading
import base64
from myutils.ConfigManager import myCongif
#独立模型线程
from core.ModelNode import ModelNode
from core.ChannelData import ChannelData #其实ChannelNode会更加贴切一些
'''
通道对象管理类,只针对通道节点的维护,和工作线程的开启和停止, ChannelData的操作必须维护在ChannelManager里面!不能输出ChannelData对象!
'''
class ChannelManager:
def __init__(self):
self._channels = {}
self.cm_lock = threading.RLock() # 用于保证字典操作的线程安全
# 独立Model_th相关参数 --- modelNode 用一个类封装下model线程和其相关参数
self.model_list = {} # model_id -- modelNode
self.workType = int(myCongif.get_data("workType"))
self.device_id = myCongif.get_data("device_id")
#增加节点
def add_channel(self, channel_id,deque_length,icount_max,warnM):
ret = False
with self.cm_lock:
if channel_id in self._channels: #若已经有数据,先删除后再增加
self._channels[channel_id].stop_work(0) # 停止工作
del self._channels[channel_id]
if self.workType == 2: # 若有model线程停止了,则删除该model节点
self.delModelNode()
#channel_id,deque_length,icount_max,warnM
ch_data = ChannelData(channel_id, deque_length, icount_max,warnM)
self._channels[channel_id] = ch_data
ret = True
return ret
#删除节点
def delete_channel(self, channel_id): #需要验证资源的释放清空
'''删除节点,包含了停止该节点工作线程'''
ret = True
with self.cm_lock:
if channel_id == 0:
for clannel_data in self._channels:
clannel_data.stop_work(0)
self._channels.clear() #清空节点
else:
if channel_id in self._channels:
self._channels[channel_id].stop_work(0) #停止工作
del self._channels[channel_id]
if self.workType == 2: #若有model线程停止了,则删除该model节点
self.delModelNode()
return ret
#开始工作线程
def start_channel(self,channel_id,cap_data,model_data,schedule,type):
'''
启动通道的工作线程 -- 启动应该没有一下子启动所有
:param channel_id: 启动通道的ID channel_id == 0的情况已经在上一层处理了,这里不会有0
:param cap_data: [source,type]
:param model_data: 跟该通道关联的模型数据
:param schedule
:param type: 0-启动所有工作线程,1-启动CAP采集线程,2-启动model工资线程
:return:
'''
ret = False
with self.cm_lock:
if channel_id in self._channels:
c_node = self._channels[channel_id]
model_node = None
if self.workType == 2 and type !=1: #需要确保当type!=1时,model_data必须有数据 -- 调用时已经有判断
model_node = self.CreateModelNode(model_data[0], model_data[5], channel_id)
ret = c_node.start_work(cap_data,model_data,schedule,type,model_node)
return ret
#停止工作线程---要把视频采集线程停止掉
def stop_channel(self,channel_id,type): #9-10截止目前就重启模型线程时用到该函数(channel_id,2)
'''
停止通道的工作线程
:param channel_id: 0-停止所有通道的工作线程,其他值为具体停止哪个工作线程
:param type: 0-停止所有工作线程,1-停止CAP采集线程,2-停止model工资线程
:return:
'''
with self.cm_lock:
ret = False
if channel_id == 0:
# for clannel_id,clannel_data in self.channels.items():
for clannel_data in self._channels:
clannel_data.stop_work(type)
ret = True
else:
if channel_id in self._channels:
self._channels[channel_id].stop_work(type)
ret =True
if self.workType == 2: #若有model线程停止了,则删除该model节点
self.delModelNode()
return ret
def get_channel_data(self,channel_id):
cdata = None
if channel_id in self._channels:
cdata = self._channels[channel_id]
return cdata
def cm_get_last_frame(self,channel_id): #这里如果加锁的话,阻塞会比较厉害,但具体程度也需要验证。
frame = None
if channel_id in self._channels:
try:
frame = self._channels[channel_id].get_last_frame()
except Exception as e:
print(e)
return frame
def cm_get_cap_frame(self,channel_id):
img_base64 = None
if channel_id in self._channels:
channel_data = self._channels[channel_id]
if channel_data.cap:
try:
for i in range(5):
ret, frame = channel_data.cap.read()
if ret:
ret, frame_bgr_webp = cv2.imencode('.jpg', frame)
if ret:
# 将图像数据编码为Base64
img_base64 = base64.b64encode(frame_bgr_webp).decode('utf-8')
break
except Exception as e:
print(e)
return img_base64
'''模型独立线程修改2024-9-9,要求是双模式兼容'''
'''2024-10-13修改独立线程为独立进程---acl初始化需要在子进程中初始化 -- 该方案无法兼容旧版本'''
def CreateModelNode(self, model_id, model_path, channel_id):
if model_id in self.model_list:
modelN = self.model_list[model_id]
else:
modelN = ModelNode(self.device_id,model_path)
self.model_list[model_id] = modelN
#modelN = ModelNode(self.device_id, model_path,channel_id)
return modelN
def delModelNode(self): #关于modelnodel :1.考虑modelnode是否可以不删除,清空inmq即可,2.mdel_list是否需要加锁。#?
return
for model_id, modelNode in self.model_list.items():
if modelNode.ch_count == 0:
del self.model_list[model_id]
if __name__ == "__main__":
# 示例使用
pass