大约十年前用过海康的硬盘录像机和SDK进行过二次开发,多年不用了,现在市场变化很大。近几年网络摄像头大量出现,如海尔、小米等品牌。相比早期海康、大华的监控摄像头,这些网络摄像头使用简单、方便,不需要单独的录像机,可通过手机远程观看和云台控制。但他们没有提供开发包,想要二次开发的用户还是要选择海康和大华。他们也推出了支持网络的录像机和摄像头。如海康有支持萤石云的录像机,支持普通模拟输入、网络输入摄像头,可通过手机或电脑观看。还有支持网络和云台的萤石摄像头,支持智能跟踪和听声辨位,可通过手机远程观看和云台控制。大华有支持网络和云台的乐橙摄像头。
我们以海康录像机NVR DS-7804为例,接入模拟摄像头进行开发。主要包括以下内容:

1.硬件准备

先安装录像机硬盘,若不安装,录像机会一直报警。然后将摄像头与录像机连接,并连接摄像头和录像机电源。接上录像机电源后,录像机会自动开机,开机过程可设置用户密码,该密码在使用录像机SDK时需要使用。该录像机默认支持4路模拟输入和1路网络输入,可设置将其中的模拟输入改为网络输入。网络输入需要将摄像头接入和录像机所在路由。设置完毕后应该可以看到摄像头输出的视频。
录像机连接网络。录像机只有一个网口,用于连接路由器。若要通过手机观看,需安装萤石云app,注册登录,并通过扫描硬盘录像机的二维码(录像机开机设置界面)添加录像机。为便于使用SDK,在录像机网络连接正常时,需记录录像机IP地址(与电脑在同一网段,可在录像机视频播放主界面通过点击鼠标右键弹出的主菜单查看)。用于调试程序的电脑也要通过有线接入该路由器。注意是有线接入。若用无线接入,即使接入同一个路由器,IP地址也与录像机不在同一网段,导致程序的录像机登录功能失败。

2.软件准备

这里使用的是Visual Studio 2015,SDK从海康官网下载。下载的文件名为CH-HCNetSDK(Windows32)V5.3.2.15_build20171122.zip,解压后打开子文件夹Demo示例,可以看到有MFC、C#、Java三种语言的示例。这里以实时预览&抓图&云台控制为例进行配置。

3.程序调试

海康给的示例使用Visual Studio 2013开发,本机只有Visual Studio 2015,因此使用Visual Studio 2015进行调试。打开sln文件时会提示升级,升级后进行调试,会出现错误提示,

“/ZI”和“/Gy-”命令行选项不兼容

可通过如下设置解决。进入“项目”—>“属性”—>“C/C++”—>“常规”—>“调试信息格式”—>选择“程序数据库(/Zi)”或“无”。
另外还需添加头文件路径和库文件路径,即CH-HCNetSDK(Windows32)V5.3.2.15_build20171122文件夹中的子文件夹“头文件”和“库文件”,并将库文件添加至项目中。方法如下:

  添加头文件目录:
  项目-->属性-->C/C++-->常规-->附加包含目录, 编辑为头文件存放目录。
  添加lib文件:
  项目-->属性-->链接器-->输入-->附加依赖项,填入库名(HCNetSDK.lib)。
  否则编译时会提示:fatal error LNK1104: 无法打开文件“×××.lib”。
  添加库文件路径:  
  项目-->属性-->链接器-->常规-->附加目录 ,编辑库文件所在的路径即可。
  添加库文件到工程中(不是必须):
  在解决方案资源管理器视图中,右键点击项目—>添加—>现有项,选择库文件,确定。

配置完成后,项目应该能生成可执行文件RealPlay.exe,点击Login按钮,若登陆成功,左侧出现摄像头列表,选择其中一个,进行播放,如图所示

登陆按钮响应函数为:

void CRealPlayDlg::OnButtonLogin() 
{   
    if(!m_bIsLogin)    //login
    {
        if(!DoLogin())
            return;
        DoGetDeviceResoureCfg();  //获取设备资源信息    
        CreateDeviceTree();        //创建通道树
        GetDecoderCfg();                           //获取云台×××信息
        InitDecoderReferCtrl();         //初始化×××相关控件      
        GetDlgItem(IDC_BUTTON_LOGIN)->SetWindowText("Logout");
        m_bIsLogin = TRUE;      
    }
    else      //logout
    {           
        if(m_bIsPlaying|| m_bIsRecording)
        {
            MessageBox("Stop Play or record first!");
            return;
        }
        NET_DVR_Logout_V30(m_struDeviceInfo.lLoginID); 
        GetDlgItem(IDC_BUTTON_LOGIN)->SetWindowText("Login");
        m_ctrlTreeChan.DeleteAllItems();
        m_struDeviceInfo.lLoginID = -1;
        m_bIsLogin = FALSE;
    }
}

若登陆界面的用户信息与初始化信息不符,会登录失败并提示错误。登陆界面的Dev IP为前面记录的录像机IP,Password为录像机开机界面设置的用户密码。这两个信息还需要在程序初始化过程设置。
录像机IP在初始化函数中设置。

BOOL CRealPlayDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Add "About..." menu item to system menu.

    // IDM_ABOUTBOX must be in the system command range.
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);
    CMenu* pSysMenu = GetSystemMenu(FALSE); 
    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);         // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon   
    // TODO: Add extra initialization here
    //默认IP
    m_ctrlDevIp.SetAddress(192,168,0,107);
    }

用户密码在对话框类构造函数中。

CRealPlayDlg::CRealPlayDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CRealPlayDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CRealPlayDlg)
        // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_nDevPort = 8000;
    m_csUser = _T("admin");
    m_csPWD = _T("114030ww");
    m_bIsLogin = FALSE;
    //m_lLoginID = -1;;
    m_bIsPlaying = FALSE;
    m_bIsRecording = FALSE;
    m_iCurChanIndex = -1;
    m_lPlayHandle = -1;
    m_bIsOnCruise = FALSE;
    m_bTrackRun = FALSE;
    m_bAutoOn = FALSE;
    m_bLightOn = FALSE;
    m_bWiperOn= FALSE;
    m_bFanOn= FALSE;
    m_bHeaterOn= FALSE;
    m_bAuxOn1= FALSE;
    m_bAuxOn2= FALSE;
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

登陆信息中的端口号8000和用户名admin不需要修改。用户名在录像机开机设置时也无法修改。
完成上述工作后,该程序应该就可以正常运行了。