Creating C# application using Hikvision SDK for DS-7116HVI-SL

Discussion in 'Cameras, NVR / DVR's, hardware & more' started by Srinivas Cheruku, Aug 3, 2017.

Share This Page

  1. curiousDev

    curiousDev n3wb

    Joined:
    Aug 16, 2017
    Messages:
    21
    Likes Received:
    1
    you're welcome :)
    I also learnt new thing. Now i know it works for camera as well.
     
  2. Vilius

    Vilius n3wb

    Joined:
    Aug 2, 2018
    Messages:
    16
    Likes Received:
    0
    Location:
    Vilnius, Lithuania
    Hello again,

    maybe someone have any ideas how can i get image from live stream? i need to get image that going to be used in Neural Networks. I tried to get image from IntPtr, but no success..
     
  3. curiousDev

    curiousDev n3wb

    Joined:
    Aug 16, 2017
    Messages:
    21
    Likes Received:
    1
    I think you will need to use NET_DVR_CaptureJPEGPicture_NEW or NET_DVR_CaptureJPEGPicture method from SDK.
     
  4. Vilius

    Vilius n3wb

    Joined:
    Aug 2, 2018
    Messages:
    16
    Likes Received:
    0
    Location:
    Vilnius, Lithuania
    I tested that function with demo sdk, and it takes too long...
     
  5. curiousDev

    curiousDev n3wb

    Joined:
    Aug 16, 2017
    Messages:
    21
    Likes Received:
    1
    I also found two other methods NET_DVR_CapturePicture and NET_DVR_CapturePictureBlock it requires live stream handle so maybe that will be better approach for you?

    Both of them have also _V50 version e.g. NET_DVR_CapturePicture_V50
     
  6. hmm hmm

    hmm hmm n3wb

    Joined:
    Jul 25, 2018
    Messages:
    1
    Likes Received:
    0
    Location:
    montreal
    Hi curiousDev, I'm having the same issue as Phonixs (green boxes from movement detection during live view)

    you said: "Maybe it is avaialbe to get rid off them by connecting to subchannel of this camera instead of main channel?"

    How do I figure out what are the subchannels of my cam?

    Actually, I don't even know how to find the main channels, I found out by luck that my main channels start at 33 but I'm struggling to find the infos.

    Thank you

    Edit: I'm connecting to a dvr (16 channels) not a cam directly
     
    Last edited: Aug 8, 2018
  7. Vilius

    Vilius n3wb

    Joined:
    Aug 2, 2018
    Messages:
    16
    Likes Received:
    0
    Location:
    Vilnius, Lithuania
    i am not sure if this is correct. I am always getting error that buffer is not enough.

    [DllImport(DLL)]
    public static extern bool NET_DVR_CapturePicture_V50(int lUserID, int lChannel,ref Structs.LPNET_DVR_PICPARAM_V50 lpPicParam, ref byte[] sPicBuffer, int dwPicSize,ref ulong lpSizeReturned);

    Structs.LPNET_DVR_PICPARAM_V50 picParam = new Structs.LPNET_DVR_PICPARAM_V50();


    byte[] data = new byte[65530];
    ulong Len = 0;
    int BuffSize = 65530;

    bool result = SDKMethods.NET_DVR_CapturePicture_V50(UserID, 1,ref picParam,ref data, BuffSize,ref Len);
    if(!result)
    {
    Console.WriteLine(errors.ErrorByCode(SDKMethods.NET_DVR_GetLastError()));
    }
     
  8. curiousDev

    curiousDev n3wb

    Joined:
    Aug 16, 2017
    Messages:
    21
    Likes Received:
    1
    Can you provide some more details?
    Best to see a part of code which you use for that.
    For now I can give u small tip it was even mention in code snippets by Vilius and me before in this thread. I am not sure if it will help you need to test it out.
    public int dwStreamType; // Stream type 0-main stream,1-sub stream,2-third stream,3-forth stream,4-fifth stream,5-sixth stream,7-seventh stream,8-eighth stream,9-ninth stream,10-tenth stream
     
  9. curiousDev

    curiousDev n3wb

    Joined:
    Aug 16, 2017
    Messages:
    21
    Likes Received:
    1
    I am pretty sure that you have some problems with dll import. parameter types are incorrect. I will try to fix it for you but i dont have oportunity to test it in this moment.

    [DllImport(DLL)] (i am not sure about 'ref byte[] sPicBuffer' can be a 'ref string sPicBuffer' or just 'string sPicBuffer')
    public static extern bool NET_DVR_CapturePicture_V50(int lUserID, int lChannel, ref Structs.LPNET_DVR_PICPARAM_V50 lpPicParam, ref byte[] sPicBuffer, unit dwPicSize, ref uint lpSizeReturned);
    or
    public static extern bool NET_DVR_CapturePicture_V50(int lUserID, int lChannel, ref Structs.LPNET_DVR_PICPARAM_V50 lpPicParam, ref byte[] sPicBuffer, unit dwPicSize, ref IntPtr lpSizeReturned);

    Let me know if it worked, ok?


    And small advice to everyone look carefully at types of variables e.g. LONG in Hik SDK isnt a long it's a defined type
    typedef int LONG;

    Most of troubles with code is caused by wrong 'mapping' to C# types.
    Tomorrow I will put a mapper to C# types of some common types from this SDK.
     
  10. Vilius

    Vilius n3wb

    Joined:
    Aug 2, 2018
    Messages:
    16
    Likes Received:
    0
    Location:
    Vilnius, Lithuania
    Hi curiousDev,

    i tried and that didn't worked. I will test this on c++ console app to see if this function works.
     
  11. curiousDev

    curiousDev n3wb

    Joined:
    Aug 16, 2017
    Messages:
    21
    Likes Received:
    1
    Hello again,

    As I promised in previous post here is a small mapper which I have made for my purposes.

    HIK SDK C++ - C#
    WORD - ushort
    DWORD - uint
    LONG - int
    char* - string
    BYTE - byte
    BOOL - bool
    void* - IntPtr (if u want to assign null then use IntPtr.Zero)
    LPVOID - IntPtr (if u want to assign null then use IntPtr.Zero)
    HWND - IntPtr
    wchar_t[] - StringBuilder (wchar_t[256] new StringBuilder(256))

    Generally i have notices that any variable in Hik SDK with prefix LP is a pointer (to structures mostly) in that case we need to use ref keyword.
    For example:
    LONG NET_DVR_Login_V40( LPNET_DVR_USER_LOGIN_INFO pLoginInfo, LPNET_DVR_DEVICEINFO_V40 lpDeviceInfo);

    struct
    { NET_DVR_DEVICEINFO_V30 struDeviceV30;
    BYTE bySupportLock;
    BYTE byRetryLoginTime;
    BYTE byPasswordLevel; BYTE byRes1;
    DWORD dwSurplusLockTime;
    BYTE byCharEncodeType;
    BYTE byRes2[255];
    } NET_DVR_DEVICEINFO_V30,*LPNET_DVR_DEVICEINFO_V30;

    As you can see LPNET_DVR_DEVICEINFO_V30 is a pointer type while NET_DVR_DEVICEINFO_V30 is non pointer type.
     
  12. curiousDev

    curiousDev n3wb

    Joined:
    Aug 16, 2017
    Messages:
    21
    Likes Received:
    1
    Is it working for you in c++?
    I was trying to do this and having soem problems as well. I found a method NET_DVR_GetDeviceAbility which should be able to check if some functionalities are available on certain device but i am having problems with this as well.
     
  13. Vilius

    Vilius n3wb

    Joined:
    Aug 2, 2018
    Messages:
    16
    Likes Received:
    0
    Location:
    Vilnius, Lithuania
    no luck with that... I am trying to use EmguCV libraries now..
     
  14. Vilius

    Vilius n3wb

    Joined:
    Aug 2, 2018
    Messages:
    16
    Likes Received:
    0
    Location:
    Vilnius, Lithuania
    I noticed interesting thing. Camera with one frame returns 34 calbacks. This is what i received:

    Date/time/buffer size/ actual buffer size
    2018-08-09 16:26:47, 116, 1
    2018-08-09 16:26:47, 72, 1
    2018-08-09 16:26:47, 20, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 5120, 1
    2018-08-09 16:26:47, 3808, 1
    2018-08-09 16:26:47, 112, 1

    i'm not sure why, but callback always returns actual buffer with only 1 element...
     
  15. Vilius

    Vilius n3wb

    Joined:
    Aug 2, 2018
    Messages:
    16
    Likes Received:
    0
    Location:
    Vilnius, Lithuania
    i think i have solution.
    i have this callback structure:
    public delegate void REALDATACALLBACK(int lPlayHandle, uint dwDataType, IntPtr pBuffer, uint dwBufSize, IntPtr pUser);
    pBuffer is pointer, which shows where my bytes are. Maximum number of bytes is 5120. So with every callback i receive 5120 bytes or less. Using Marshal i can copy bytes from memory to my Byte[] array. Last thing i have to do, is to make very long byte array and put everything together. Tomorrow i will try to make picture from that information
     
  16. curiousDev

    curiousDev n3wb

    Joined:
    Aug 16, 2017
    Messages:
    21
    Likes Received:
    1
    I got it working. It's kinda tricky to make it work properly.

    Dont know why you didnt use normal version of NET_DVR_CapturePicture instead of NET_DVR_CapturePicture_V50 but i believe you had some reasons.

    The NET_DVR_CapturePicture is much more easier and could be done within 5 mins.

    Anyway I am going to share with both of solutions. It was quiet good chellenge for me and i couldnt take care of that earlier. Now after 2-3h struggling in total I got the solution.

    Dll import:

    [DllImport(@"\Hikvision\CppDlls\HCNetSDK.dll", EntryPoint = "NET_DVR_CapturePicture")]
    public static extern bool NET_DVR_CapturePicture(int lRealHandle, string sPicFileName);

    [DllImport(@"\Hikvision\CppDlls\HCNetSDK.dll", EntryPoint = "NET_DVR_CapturePicture_V50")]
    public static extern bool NET_DVR_CapturePicture_V50(int lUserID, int lChannel, ref NET_DVR_PICPARAM_V50 lpPicParam, IntPtr sPicBuffer, uint dwPicSize, ref uint lpSizeReturned);

    structure definitions:

    public struct NET_DVR_PICPARAM_V50
    {
    public NET_DVR_JPEGPARA struParam;
    public byte byPicFormat;
    public byte byCapturePicType;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 254, ArraySubType = UnmanagedType.I1)]
    public byte[] byRes;
    }


    public struct NET_DVR_JPEGPARA
    {
    /*Note: If encoding resolution is VGA, it supports grabbing 0=CIF, 1=QCIF, 2=D1 image.
    But if encoding resolution is 3=UXGA (1600x1200) , 4=SVGA (800x600) , 5=HD720p (1280x720) , 6=VGA, 7=XVGA, and 8=HD900p it only support grabbing image with current resolution*/
    /*
    0-CIF, 1-QCIF, 2-D1, 3-UXGA(1600x1200), 4-SVGA(800x600),5-HD720p(1280x720),
    6-VGA, 7-XVGA, 8-HD900p, 9-HD1080, 10-2560*1920,
    11-1600*304, 12-2048*1536, 13-2448*2048, 14-2448*1200, 15-2448*800,
    16-XGA(1024*768), 17-SXGA(1280*1024),18-WD1(960*576/960*480), 19-1080i, 20-576*576,
    21-1536*1536, 22-1920*1920, 23-320*240, 24-720*720, 25-1024*768,
    26-1280*1280, 27-1600*600, 28-2048*768, 29-160*120, 75-336*256,
    78-384*256, 79-384*216, 80-320*256, 82-320*192, 83-512*384,
    127-480*272, 128-512*272, 161-288*320, 162-144*176, 163-480*640,
    164-240*320, 165-120*160, 166-576*720, 167-720*1280, 168-576*960,
    500-384*288,
    0xff-Auto(Use resolution of current stream)
    */
    public ushort wPicSize;
    public ushort wPicQuality; /* 0 - the best, 1 - better, 2 - average; */
    }


    calling 'normal' version (keep in mind it requires RealPlay) (not 100% sure but I guess it saves as bmp only):

    string picPath = @"D:\Temp\pic.bmp";
    bool picCaptured = SDKMethods.NET_DVR_CapturePicture(realPlayId, picPath);
    if (!picCaptured)
    {
    string message = string.Format("RealPlay failed, error code: {0}\n", SDKMethods.NET_DVR_GetLastError());
    Console.WriteLine(message);
    result.AddError(message);
    result.IsSuccessful = false;
    SDKMethods.NET_DVR_StopRealPlay(realPlayId);
    SDKMethods.NET_DVR_Logout(lUserID);
    SDKMethods.NET_DVR_Cleanup();
    return result;
    }

    calling V50 version (saves as jpg file):

    NET_DVR_JPEGPARA jpegParam = new NET_DVR_JPEGPARA();
    jpegParam.wPicQuality = 0;
    jpegParam.wPicSize = 0xff;
    NET_DVR_PICPARAM_V50 picParam_V50 = new NET_DVR_PICPARAM_V50();
    picParam_V50.struParam = jpegParam;
    picParam_V50.byCapturePicType = 0;
    picParam_V50.byPicFormat = 0;
    uint picSize = 2500 * 2048;
    StringBuilder picBufferStr = new StringBuilder((int)picSize);
    byte[] picBuffer = new byte[picSize];
    IntPtr picBufferPtr = new IntPtr();
    uint lpSizeReturned = 0;
    int channel = 36;
    picBufferPtr = Marshal.AllocHGlobal(picBuffer.Length);
    Marshal.Copy(picBuffer, 0, picBufferPtr, picBuffer.Length);

    bool picCaptured = SDKMethods.NET_DVR_CapturePicture_V50(lUserID, channel, ref picParam_V50, picBufferPtr, picSize, ref lpSizeReturned);
    if (!picCaptured)
    {
    string message = string.Format("CapturePicture_V50 failed, error code: {0}\n", SDKMethods.NET_DVR_GetLastError());
    Console.WriteLine(message);
    result.AddError(message);
    result.IsSuccessful = false;
    SDKMethods.NET_DVR_Logout(lUserID);
    SDKMethods.NET_DVR_Cleanup();
    return result;
    }
    byte[] imageRawData = new byte[(int)lpSizeReturned];
    Marshal.Copy(picBufferPtr, imageRawData, 0, (int)lpSizeReturned);
    System.IO.MemoryStream buf = new System.IO.MemoryStream(imageRawData);
    Image image = Image.FromStream(buf, true);
    image.Save(@"D:\Temp\test.jpg");
     
  17. Vilius

    Vilius n3wb

    Joined:
    Aug 2, 2018
    Messages:
    16
    Likes Received:
    0
    Location:
    Vilnius, Lithuania
    hi curiousDev,

    none of those methods are good enough for me.
    NET_DVR_CapturePicture saves picture in computer.
    NET_DVR_CapturePicture_V50 saves in byte array, but it gives me only 1fps.. I need pictures in byte arrays but framerate should be as high as possible.
     
  18. curiousDev

    curiousDev n3wb

    Joined:
    Aug 16, 2017
    Messages:
    21
    Likes Received:
    1
    Hey Vilius,

    Cannot you just call method NET_DVR_CapturePicture_V50 n times to get more frames? I wasnt trying trough but i think it might be a solution at least partial.
    Similar to V50 is also NET_DVR_CapturePictureBlock_New so it might come with help.
     
  19. Vilius

    Vilius n3wb

    Joined:
    Aug 2, 2018
    Messages:
    16
    Likes Received:
    0
    Location:
    Vilnius, Lithuania
    i tried, but it returns only one picture per second.
    i guess i have to capture whole package and then try to decode from h.254 format. I am going to do c++ wrapper for that
     
  20. Mechalec

    Mechalec n3wb

    Joined:
    Jul 25, 2018
    Messages:
    2
    Likes Received:
    0
    Location:
    Australia
    Again, thanks to all that are contributing on this thread. It is extremely helpful. I have had some time away but only now revisiting my code.

    I have managed to login successfully to my camera and start the live data stream. Reverted to C++ but will revert back to C# with the help from CuriousDev.

    I am now confused as to what to do with that live video stream. (data only)

    My main goal is to start a live stream to a camera and then save this to a file in what ever video format necessary (e.g MP4).

    I open a stream to the camera and it responds by supplying a system header, it then starts streaming data, but I am unsure of how that data is packaged.
     
    Last edited: Aug 11, 2018
  21. curiousDev

    curiousDev n3wb

    Joined:
    Aug 16, 2017
    Messages:
    21
    Likes Received:
    1
    Hi Mechalec,

    Try use NET_DVR_SaveRealData or NET_DVR_SaveRealData_V30 it requires to open realplay though but I am sure that is what u are looking for.
     
  22. DannyDS

    DannyDS n3wb

    Joined:
    Sep 25, 2017
    Messages:
    2
    Likes Received:
    0
    I know its to do with video playback but its the only thread i've seen active involving the Hikvision SDK, has anyone had any experience with Net_DVR_StartListenV30?

    When starting the listen i get error 109 - Alarm component is failed to upload

    Ive got an old set of the SDK libraries from 2015 which when used instead allow me to start listening but has some errors with the alarm data recieved.

    Any help appreciated, thanks
     
  23. curiousDev

    curiousDev n3wb

    Joined:
    Aug 16, 2017
    Messages:
    21
    Likes Received:
    1
    Hello DannyDS,

    Like for me it looks like an error referencing to missing dll. Check previous posts I've made a screenshot of directory structure.
     
  24. Vilius

    Vilius n3wb

    Joined:
    Aug 2, 2018
    Messages:
    16
    Likes Received:
    0
    Location:
    Vilnius, Lithuania
    Quick update.

    i used PlayCtrl.dll

    [DllImport("PlayCtrl.dll")]
    public static extern bool PlayM4_GetPort(ref int Port);

    [DllImport("PlayCtrl.dll")]
    public static extern bool PlayM4_SetStreamOpenMode(int port, int mode);

    [DllImport("PlayCtrl.dll")]
    public static extern bool PlayM4_OpenStream(int nPort, IntPtr pFileHeadBuf, uint nSize, int nBufPoolSize);

    [DllImport("PlayCtrl.dll")]
    public static extern bool PlayM4_Play(int nPort, IntPtr hWnd);

    [DllImport("PlayCtrl.dll")]
    public static extern bool PlayM4_InputData(int nPort, IntPtr pBuf, uint nSize);

    [DllImport("PlayCtrl.dll")]
    public static extern bool PlayM4_GetJPEG(int nPort, IntPtr pJpeg, uint nBufSize, ref int pJpegSize);

    [DllImport("PlayCtrl.dll")]
    public static extern bool PlayM4_GetBMP(int nPort, IntPtr pBitmap, uint nBufSize, ref int pBmpSize);


    this is my realDataCallback:

    public void VideoCallback(int lPlayHandle, uint dwDataType, IntPtr pBuffer, uint dwBufSize, IntPtr pUser)
    {
    if(dwDataType == 1)
    {

    if (!SDKMethods.PlayM4_GetPort(ref lPort))
    {
    return;
    }
    m_iPort = lPort;
    if (dwBufSize > 0)
    {
    if (!SDKMethods.PlayM4_SetStreamOpenMode(lPort, Defines.STREAME_FILE)) //or just 1
    {
    return;
    }

    if (!SDKMethods.PlayM4_OpenStream(lPort, pBuffer, dwBufSize, 1024 * 1024))
    //Open stream
    {
    return;
    }

    if (!SDKMethods.PlayM4_Play(lPort, IntPtr.Zero)) //Start play
    {
    return;
    }
    }
    }

    else
    {
    if (dwBufSize > 0 && lPort != -1)
    {
    if (!SDKMethods.PlayM4_InputData(lPort, pBuffer, dwBufSize))
    {

    return;
    }
    if(dwBufSize == 20)
    {
    new Task(() => { GetImage(); }).Start();
    }

    }
    }
    }


    public void GetImage()
    {
    int buffSize = 0;
    bool rez = SDKMethods.PlayM4_GetBMP(lPort, AllocatedMem, 1280 * 720 * 5, ref buffSize);
    //bool rez = SDKMethods.PlayM4_GetJPEG(lPort, AllocatedMem, 1280 * 720 * 5,ref buffSize);
    byte[] Data = new byte[buffSize];
    Marshal.Copy(AllocatedMem, Data, 0, buffSize);
    try
    {
    using (image = Image.FromStream(new MemoryStream(Data)))
    {
    OnNewImageReceived();
    //image.Save("output.jpg", ImageFormat.Png); // Or Png
    }
    }
    catch (Exception ex)
    {
    Console.WriteLine(ex.Message);
    }
    }

    also, dont forget to allocate memory IntPtr AllocatedMem = Marshal.AllocHGlobal(1280 * 720 * 5);

    with these steps i am now receiving picture with around 300ms delay.

    I have uploaded .rar archive with required dll
     

    Attached Files:

  25. Vilius

    Vilius n3wb

    Joined:
    Aug 2, 2018
    Messages:
    16
    Likes Received:
    0
    Location:
    Vilnius, Lithuania
  26. DannyDS

    DannyDS n3wb

    Joined:
    Sep 25, 2017
    Messages:
    2
    Likes Received:
    0
  27. wolfblaster

    wolfblaster n3wb

    Joined:
    Friday
    Messages:
    3
    Likes Received:
    0
    Location:
    Belgium
    does someone have experience with the functions NET_DVR_GetSTDAbility.

    while i'm pretty sure the camera has unattendedBaggage capabilities i still get false and lpAbilityParam stays empty.

    so far i have the following:

    public struct NET_DVR_STD_ABILITY
    {
    IntPtr lpCondBuffer;
    int dwCondSize;
    IntPtr lpOutBuffer;
    int dwOutSize;
    IntPtr lpStatusBuffer;
    int dwStatusSize;
    int dwRetSize;
    byte byRes;
    }

    [DllImport("HCNetSDK")]
    public static extern bool NET_DVR_GetSTDAbility(int lUserID, int dwAbilityType, ref NET_DVR_STD_ABILITY lpAbilityParam);

    int userId = CHCNetSDK.NET_DVR_Login_V30(...);
    CHCNetSDK.NET_DVR_STD_ABILITY ability = new CHCNetSDK.NET_DVR_STD_ABILITY();
    bool result = CHCNetSDK.NET_DVR_GetSTDAbility(userId, 3556, ref ability);
     
Tags: