前言

     本章将服务器端几个非主要但常用的功能分享一下。

 

注意

本系列文章限于学习交流,注重过程,由于涉及公司,所以不提供源代码下载,非常抱歉!!但是请大家放心,核心、实现以及其他能够贴出来的代码我都会贴出来,并且争取尽所能的回答留言里的每一个问题,感谢大家关注,欢迎交流 :)

 

系列

1.     C# 视频监控系列(1):准备

C# 视频监控系列(2):客户端——封装API

C# 视频监控系列(3):客户端——连接服务器

C# 视频监控系列(4):客户端——音频接收和抓图

C# 视频监控系列(5):客户端——给服务器端发送字符串和录像(数据捕获)

C# 视频监控系列(6):服务器端——封装API(上) [HikServer.dll]

C# 视频监控系列(7):服务器端——封装API(下) [DS40xxSDK.dll]

C# 视频监控系列(8):服务器端——预览和可被客户端连接

     9.   C# 视频监控系列(9):服务器端——数据捕获(抓图 + 录像)

C# 视频监控系列(10):服务器端——验证、设置画面质量、字幕叠加、板卡序列号

  

正文

     一、验证

          1.1     IP验证

               VC++ Code:

OnInitDialog方法
 
 
MP4_ServerCheckIP(CheckIP);
 
 
                    CheckIP委托
 
 
int 
   CALLBACK CheckIP(DWORD nChannel, 
  char 
  * 
   nIP)
 {
 
  /* 
  
     CString ctemp;
     ctemp.Format("%s",nIP);

     if (ctemp == "192.0.0.215")
         return -1;
 
  */ 
  
      
  return 
    
  0 
  ;

 } 
 
                    代码说明:
                         1.     自带的例子IP验证部分注释掉了,但是可以看得出返回-1表示错误,返回0表示验证通过,并且实际证明如果返回-1的话客户端是不出图像的。
 
               C# Code:
 
 
         
  /// 
    
  <summary> 
  
          
  /// 
   验证IP
          
  /// 
    
  </summary> 
  
          
  /// 
    
  <param name="nChannel"> 
  通道号 
  </param> 
  
          
  /// 
    
  <param name="nIP"> 
  ip地址 
  </param> 
  
          
  /// 
    
  <returns></returns> 
  
 
           
  public 
    
  int 
   CheckIP( 
  int 
   nChannel,  
  string 
   nIP)
         {
              
  // 
  验证代码 
  
 
               
  return 
    
  0 
  ;
         } 
 
                代码说明:
                    1.     比较简单,填写自己的验证代码,正确返回0,不正确反正-1就可以了。
          1.2     用户名密码验证
               VC++ Code:
OnInitDialog方法
 
 
MP4_ServerCheckPassword(checkpassword);
 
 
CheckPassword委托
 
 
int 
   CALLBACK checkpassword( 
  char 
    
  * 
  username,WORD namelen, 
  char 
    
  * 
  password,WORD passlen)
 {
 
  /* 
  
     if ((username[0] == '1') && (username[1] == '2') && (username[2] == '3') && (password[0] == 'w'))
         return 0;
     else
         return -1;
 
  */ 
  
      
  return 
    
  0 
  ;

 } 
 
               C# Code:
 
 
         
  /// 
    
  <summary> 
  
          
  /// 
   验证用户名密码
          
  /// 
    
  </summary> 
  
          
  /// 
    
  <param name="username"> 
  用户名 
  </param> 
  
          
  /// 
    
  <param name="namelen"> 
  用户名长度 
  </param> 
  
          
  /// 
    
  <param name="password"> 
  密码 
  </param> 
  
          
  /// 
    
  <param name="passlen"> 
  密码长度 
  </param> 
  
          
  /// 
    
  <returns></returns> 
  
 
           
  public 
    
  int 
   CheckPassword( 
  string 
   username,  
  ushort 
   namelen,  
  string 
   password,  
  ushort 
   passlen)
         {
              
  // 
  验证代码 
  
 
               
  return 
    
  0 
  ;
         } 
 
               这部分和验证IP差不多,唯一需要注意的是把委托写成成员变量!!
 
     二、设置画面采集质量 
           从VC++例子中Settings中可以看到这个设置:
 


   VC++ Code:
OnSettings()
 
 
switch 
  (dlg.m_iEncodeType)
             {
              
  case 
    
  0 
  :
                 encodeType  
  = 
   ENC_4CIF_FORMAT;
                  
  break 
  ;
              
  case 
    
  1 
  :
                 encodeType  
  = 
   ENC_2CIF_FORMAT;
                  
  break 
  ;
              
  case 
    
  2 
  :
                 encodeType  
  = 
   ENC_DCIF_FORMAT;
                  
  break 
  ;
              
  case 
    
  3 
  :
                 encodeType  
  = 
   ENC_CIF_FORMAT;
                  
  break 
  ;
              
  case 
    
  4 
  :
                 encodeType  
  = 
   ENC_QCIF_FORMAT;
                  
  break 
  ;
              
  default 
  :
                 encodeType  
  = 
   ENC_CIF_FORMAT;
                  
  break 
  ;
             }
              
  for 
  (i  
  = 
    
  0 
  ; i  
  < 
   GetTotalDSPs(); i 
  ++ 
  )
             {
                  
  if 
  (encodeType  
  != 
   ENC_4CIF_FORMAT)
                 {                    
                     SetEncoderPictureFormat(ChannelHandle[i],encodeType);
                 }
                  
  else 
    
  if 
   ((i 
  % 
  4 
  == 
  0 
  ) 
  || 
  (i 
  % 
  4 
  == 
  1 
  ))
                 {                    
                     SetEncoderPictureFormat(ChannelHandle[i],encodeType);
                 }
             } 
 
          C# Code:
 
 
         
  /// 
    
  <summary> 
  
          
  /// 
   设置当前所有摄头录制的画面质量
          
  /// 
    
  </summary> 
  
          
  /// 
    
  <param name="ChannelHandle"></param> 
  
          
  /// 
    
  <param name="t"> 
  编码图像分辨率 
  </param> 
  
 
           
  public 
    
  static 
    
  void 
   SetCurrentEncoderPictureFormat(IntPtr[] ChannelHandle, PictureFormat_t t)
         {
              
  for 
   ( 
  int 
   i  
  = 
    
  0 
  ; i  
  < 
   ChannelHandle.Length; i 
  ++ 
  )
             {
                 HikVisionSDK.SetEncoderPictureFormat(ChannelHandle[i], t);
             }
         } 
 
          代码说明:
PictureFormat_t说明:
PictureFormat_t.ENC_QCIF_FORMAT
PictureFormat_t.ENC_CIF_FORMAT
PictureFormat_t.ENC_DCIF_FORMAT
PictureFormat_t.ENC_4CIF_FORMAT
               2.     设置后画面效果能实时改变。
 
 
字幕叠加
一般用于显示公司LOGO和日期,下图黄色区域所示
 


  VC ++ Code:
OnSettings()
 
 USHORT Format1[ 
  40 
  ]  
  = 
   { 
  48 
  ,  
  16 
  ,  
  ' 
  H 
  ' 
  , 
  ' 
  I 
  ' 
  , 
  ' 
  K 
  ' 
  , 
  ' 
  V 
  ' 
  ,  
  ' 
  I 
  ' 
  , 
  ' 
  S 
  ' 
  , 
  ' 
  I 
  ' 
  , 
  ' 
  O 
  ' 
  , 
  ' 
  N 
  ' 
  ,  
  ' 
  \0 
  ' 
  };
 USHORT Format2[ 
  40 
  ]  
  = 
   { 
  24 
  ,  
  50 
  , _OSD_YEAR4,  
  ' 
  - 
  ' 
  ,_OSD_MONTH2, 
  ' 
  - 
  ' 
  ,_OSD_DAY, 
  ' 
  - 
  ' 
  ,  _OSD_HOUR24,  
  ' 
  : 
  ' 
  , _OSD_MINUTE, 
  ' 
  : 
  ' 
  , _OSD_SECOND,  
  ' 
  \0 
  ' 
  };


 
  // 
  
其他代码 
  
 
  
 
  for 
  (i  
  = 
    
  0 
  ; i  
  < 
   GetTotalDSPs(); i 
  ++ 
  ){
     SetOsdDisplayMode(ChannelHandle[i],  
  255 
  , TRUE,  
  0 
  , Format1, Format2);
     SetOsd(ChannelHandle[i], TRUE);
 }  
          C# Code:          
  
        private     
  const 
    
  ushort 
   _OSD_BASE  
  = 
    
  0x9000 
  ;
            private 
    
  const 
    
  ushort 
   _OSD_YEAR4  
  = 
   _OSD_BASE  
  + 
    
  0 
  ;
            private 
    
  const 
    
  ushort 
   _OSD_YEAR2  
  = 
   _OSD_BASE  
  + 
    
  1 
  ;
            private 
    
  const 
    
  ushort 
   _OSD_MONTH3  
  = 
   _OSD_BASE  
  + 
    
  2 
  ;
            private 
    
  const 
    
  ushort 
   _OSD_MONTH2  
  = 
   _OSD_BASE  
  + 
    
  3 
  ;
            private 
    
  const 
    
  ushort 
   _OSD_DAY  
  = 
   _OSD_BASE  
  + 
    
  4 
  ;
            private 
    
  const 
    
  ushort 
   _OSD_WEEK3  
  = 
   _OSD_BASE  
  + 
    
  5 
  ;
            private 
    
  const 
    
  ushort 
   _OSD_CWEEK1  
  = 
   _OSD_BASE  
  + 
    
  6 
  ;
            private 
    
  const 
    
  ushort 
   _OSD_HOUR24  
  = 
   _OSD_BASE  
  + 
    
  7 
  ;
            private 
    
  const 
    
  ushort 
   _OSD_HOUR12  
  = 
   _OSD_BASE  
  + 
    
  8 
  ;
            private 
    
  const 
    
  ushort 
   _OSD_MINUTE  
  = 
   _OSD_BASE  
  + 
    
  9 
  ;
            private 
    
  const 
    
  ushort 
   _OSD_SECOND  
  = 
   _OSD_BASE  
  + 
    
  10 
  ;

            /// 
    
  <summary> 
  
            /// 
   设置Osd
            /// 
    
  </summary> 
  
            /// 
    
  <param name="ChannelHandle"></param> 
  
            /// 
    
  <param name="setValue"></param> 
  
            
  public 
    
  void 
   SetOsd(IntPtr[] ChannelHandle,  
  bool 
   setValue)
         {
                if 
   (setValue)
             {
                    ushort 
  [] Format1  
  = 
    
  new 
    
  ushort 
  []{  
  48 
  ,  
  16 
  ,  
  ' 
  H 
  ' 
  ,  
  ' 
  I 
  ' 
  ,  
  ' 
  K 
  ' 
  ,  
  ' 
  V 
  ' 
  ,  
  ' 
  I 
  ' 
  ,  
  ' 
  S 
  ' 
  ,  
  ' 
  I 
  ' 
  ,  
  ' 
  O 
  ' 
  ,  
  ' 
  N 
  ' 
  ,  
  ' 
  \0 
  ' 
   };
                    ushort 
  [] Format2  
  = 
    
  new 
    
  ushort 
  []{  
  24 
  ,  
  50 
  , _OSD_YEAR4,  
  ' 
  - 
  ' 
  , _OSD_MONTH2,  
  ' 
  - 
  ' 
  , _OSD_DAY,  
  ' 
  - 
  ' 
  , _OSD_HOUR24,  
  ' 
  : 
  ' 
  , _OSD_MINUTE,  
  ' 
  : 
  ' 
  , _OSD_SECOND,  
  ' 
  \0 
  ' 
   };

                    for 
   ( 
  int 
   i  
  = 
    
  0 
  ; i  
  < 
   ChannelHandle.Length; i 
  ++ 
  )
                 {
                     HikVisionSDK.SetOsdDisplayMode(ChannelHandle[i],    255 
  ,  
  true 
  ,  
  0 
  , Format1, Format2);
                     HikVisionSDK.SetOsd(ChannelHandle[i],    true 
  );
                 }
             }
                else 
  
             {
                    for 
   ( 
  int 
   i  
  = 
    
  0 
  ; i  
  < 
   ChannelHandle.Length; i 
  ++ 
  )
                 {
                     HikVisionSDK.SetOsd(ChannelHandle[i],    false 
  );
                 }
             }
         }  
               代码说明:
                    1.     注意设置中文字符有问题,暂时没有解决。
                    2.     关于时间显示可以翻阅API文档,说明得很详细。
 
四、获取板卡序列号
VC++ Code: 这段代码并不在Net Server Demo项目里面,而是在System Demo(Src\SysDemoSource)项目里。
          BoardList.cpp
  
       char 
   str[ 
  100 
  ];
        char 
   sn[ 
  12 
  + 
  1 
  ];
     
     m_list.DeleteAllItems();
     boardCount   = 
  GetBoardCount();
        for 
  (UINT board 
  = 
  0 
  ;board 
  < 
  boardCount;board 
  ++ 
  )
     {
         GetBoardDetail(board,   & 
  boardDetail);
            for 
  (UINT i 
  = 
  0 
  ;i 
  < 
  12 
  ;i 
  ++ 
  )
             sn[i]   = 
  boardDetail.sn[i] 
  + 
  0x30 
  ;
         sn[   12 
  ] 
  = 
  0 
  ;
         sprintf(str,   " 
  Board:%2u Type:%s,SN:%s 
  " 
  ,
             board,boardType[boardDetail.type],sn);  
C# Code:
  
           /// 
    
  <summary> 
  
            /// 
   获取板卡序号
            /// 
    
  </summary> 
  
            /// 
    
  <returns></returns> 
  
            
  public 
    
  static 
    
  string 
   GetBoardSN()
         {
                uint 
   boardCount  
  = 
   HikVisionSDK.GetBoardCount();
             StringBuilder sn    = 
    
  new 
   StringBuilder();
                for 
   ( 
  uint 
   i  
  = 
    
  0 
  ; i  
  < 
   boardCount; )
             {
                 DS_BOARD_DETAIL boardDetail    = 
    
  new 
   DS_BOARD_DETAIL();
                 HikVisionSDK.GetBoardDetail(i,    ref 
   boardDetail);
                    for 
   ( 
  int 
   j  
  = 
    
  0 
  ; j  
  < 
    
  12 
  ; j 
  ++ 
  )
                 {
                     sn.Append((   char 
  )(boardDetail.sn[j]  
  + 
    
  0x30 
  ));
                 }
                    break 
  ;
             }
                return 
   sn.ToString();
         }


代码说明:

boardDetail.sn[j]的类型转换。

 

  五、文章后期维护

    5.1  2010-10-9  OSD显示汉字办法
 

      

汉字"保"的机器内码是"B1A3H",将如下代码替换:

      替换前:new ushort[]{ 48, 16, 'H', 'I', 'K', 'V', 'I', 'S', 'I', 'O', 'N', '\0' };

      替换后:new ushort[]{ 48, 16, 0xB1A3, 'I', 'K', 'V', 'I', 'S', 'I', 'O', 'N', '\0' };

      这样就能显示汉字了,这里再次感谢,也欢迎大家分享和交流!

 

结束

      服务器端和客户端一样三篇文章,至此结束,接下来是播放器。感谢大家继续关注该系列文章!!