纯python实现的视频监控客户端软件(二)

  • 回顾
  • 让我们回顾一下上次的内容,test.py 文件中那6行代码实现的c++ dll加载:


    import os

    from ctypes import *

    APP_PATH = os.path.dirname(os.path.abspath(__file__))

    hcnetsdk = cdll.LoadLibrary(APP_PATH + ‘\HCNetSDK.dll’)

    hcpreview = cdll.LoadLibrary(APP_PATH + ‘\HCPreview.dll’)

    hcplayback = cdll.LoadLibrary(APP_PATH + ‘\HCPlayBack.dll’)


  • 继续
  • 本来想直接贴全部代码,结果头条说我的字数太多,不能发布,只能一点点按顺序贴,麻烦各位一部分一部分的拷贝了,不过这样也有利于我每贴一段,进行一定程度的代码解释备注。

  • 库导入
  • 接着写,我们需要导入如下的库:


    from PyQt5.QtWidgets import *

    from PyQt5.QtCore import *

    from PyQt5.QtGui import *

    import pickle

    import sys


    PyQT5 是诺基亚的一套老牌的跨界面开发包,利用它我们可以轻松开发windows/linux界面应用程序。

    pickle是用于配置文件读写的库,本例中用于读写IP、端口、用户名、密码等配置;

    sys是系统库,我们需要在创建QT程序时用到它。

  • 结构定义与转换
  • 以 python 的方式来定义 c++ 结构体,我们先看一下HCNetSDK.h中的原始c++定义:

    NET_DVR_DEVICEINFO

    NET_DVR_CLIENTINFO

    再看我们在 python 中的转换代码如下:


    SERIALNO_LEN = 48 #SN length

    class NET_DVR_DEVICEINFO(Structure):

    _fields_ = [(“sSerialNumber”, c_byte * SERIALNO_LEN), #SN

    (“byAlarmInPortNum”, c_byte), #DVR Alarm input

    (“byAlarmOutPortNum”, c_byte), #DVR Alarm Output

    (“byDiskNum”, c_byte), #DVR Number of Hard Disk

    (“byDVRType”, c_byte), #DVR Type, 1: DVR 2: ATM DVR 3: DVS ……

    (“byChanNum”, c_byte), #DVR Number of Channel

    (“byStartChan”, c_byte) #The first Channel No. E.g. DVS- 1, DVR- 1

    ]

    #Preview via software decoding

    class NET_DVR_CLIENTINFO(Structure):

    _fields_ = [(“lChannel”, c_long), #channel no.

    (“lLinkMode”, c_long), #If 31st bit is 0, it means connect main stream, is 1 means sub stream. Bit 0~bit 30 are used for link mode: 0: TCP mode, 1: UDP mode, 2: Multi- play mode, 3: RTP mode,4-RTP/RTSP,5-RSTP/HTTP

    (“hPlayWnd”, c_uint32), #the play window’s handle; set NULL to disable preview

    (“sMultiCastIP”, c_char_p), #Multicast group

    (“byProtoType”, c_byte), #0-private protocol,1-RTSP protocol

    (“byRes”, c_byte * 3)

    ]


    结构体 NET_DVR_DEVICEINFO 是调用海康登录函数时需要传入的参数:

    结构体 NET_DVR_CLIENTINFO 是调用海康预览函数时需要传入的参数;

    这里对重要的几个参数解释一下:

    lLinkMode 为0代表取主码流、为1代表取子码流;

    hPlayWnd 指定你需要显示视频内容的窗口;

    从上可以看出,python 直接调用 c++ dll,最大的困难在于在两个语言之间进行适当的结构体、变量类型的转换,这不仅要求你对两种语言都非常熟悉,而且还要去你对windows API 编程要熟悉,特别是 windows 基于c/c++定义的一些操作系统变量类型,比如:DWORD、WORD等,这块对于初学者来说并不是那么友好。

  • 函数定义与转换
  • 同样,除了结构体的转换,我们还必须完成函数的转换,让我们先看看 HCNetSDK.h 中的原始c++函数定义,如下是部分截图:

    我们必须转换函数的参数为 python 能够认知的类型,所以,接下来我在 python 中定义了 HCNetSDK 这个类,来实现所有的参数转换:


    class HCNetSDK:

    def NET_DVR_Init(self):

    return hcnetsdk.NET_DVR_Init()

    def NET_DVR_SetReconnect(self, dwInterval=30000, bEnableRecon=True):

    return hcnetsdk.NET_DVR_SetReconnect(dwInterval, bEnableRecon)

    def NET_DVR_Login(self, sDVRIP, wDVRPort, sUserName, sPassword):

    di = NET_DVR_DEVICEINFO()

    pdi = byref(di)

    return hcnetsdk.NET_DVR_Login(str.encode(sDVRIP), wDVRPort, str.encode(sUserName), str.encode(sPassword), pdi)

    def NET_DVR_Logout(self, lUserID):

    return hcnetsdk.NET_DVR_Logout(lUserID)

    def NET_DVR_Cleanup(self):

    return hcnetsdk.NET_DVR_Cleanup()

    def NET_DVR_RealPlay(self, lUserID, lChannel, hPlayWnd):

    ci = NET_DVR_CLIENTINFO()

    ci.lChannel = lChannel

    ci.hPlayWnd = hPlayWnd

    pci = byref(ci)

    return hcnetsdk.NET_DVR_RealPlay(lUserID, pci)

    def NET_DVR_StopRealPlay(self, lRealHandle):

    return hcnetsdk.NET_DVR_StopRealPlay(lRealHandle)

    def NET_DVR_GetLastError(self):

    return hcnetsdk.NET_DVR_GetLastError()

    def NET_DVR_GetSDKVersion(self):

    return hcnetsdk.NET_DVR_GetSDKVersion()

    def NET_DVR_GetSDKBuildVersion(self):

    return hcnetsdk.NET_DVR_GetSDKBuildVersion()


    同样这些转换对于初学者来说不太友好,你必须理解指针、常量指针、结构指针、引用等等一些概念,因此,直接拷贝代码好了,本例只写了10个函数,如果你要扩展其他函数,可以依样画葫芦,或者有问题在评论区留言好了。

  • 结语
  • 由于头条篇幅的限制,我们紧接着下一篇文章继续贴代码。

    声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

    上一篇 2020年10月5日
    下一篇 2020年10月5日

    相关推荐