1
zhanghua
2024-09-26 c775c6953d9759e70f08acbfa8f6d7490aaae3d1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
package com.netsdk.demo.customize;
 
import java.util.Date;
import java.io.File;
import java.text.SimpleDateFormat;
 
import com.netsdk.demo.util.CaseMenu;
import com.netsdk.demo.util.Testable;
import com.netsdk.lib.NetSDKLib;
import com.netsdk.lib.NetSDKLib.LLong;
import com.netsdk.lib.ToolKits;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
 
/**
 * 适用于 IPC, 球机等非智能交通、停车场设备
 * 包括同步抓图和异步抓图
 * @author 29779
 *
 */
public class SnapPicture implements Testable {
    
    static NetSDKLib netsdkApi     = NetSDKLib.NETSDK_INSTANCE;
    static NetSDKLib configApi     = NetSDKLib.CONFIG_INSTANCE;
 
    private LLong loginHandle;
    
    private static class DisconnectCallback implements NetSDKLib.fDisConnect {
        private static DisconnectCallback instance = new DisconnectCallback();
        private DisconnectCallback() {}
        public static DisconnectCallback getInstance() { 
            return instance;
        }
        
        public void invoke(LLong lLoginID, String pchDVRIP, int nDVRPort, Pointer dwUser){
            System.out.printf("Device[%s:%d] Disconnect!\n" , pchDVRIP , nDVRPort);
        }
    }
    
    private static class HaveReconnectCallback implements NetSDKLib.fHaveReConnect {
        private static HaveReconnectCallback instance = new HaveReconnectCallback();
        private HaveReconnectCallback() {}
        public static HaveReconnectCallback getInstance() { 
            return instance;
        }
        
        public void invoke(LLong lLoginID, String pchDVRIP, int nDVRPort, Pointer dwUser){
            System.out.printf("Device[%s:%d] HaveReconnected!\n" , pchDVRIP , nDVRPort);
        }
    }    
 
    @Override
    public void initTest() {
        //初始化SDK库
        netsdkApi.CLIENT_Init(DisconnectCallback.getInstance(), null);
        
        //设置断线自动重练功能
        netsdkApi.CLIENT_SetAutoReconnect(HaveReconnectCallback.getInstance(), null);
        
        // 向设备登入
        final int nSpecCap = 0; /// login device by TCP
        final IntByReference error = new IntByReference();
        final String address = "172.23.1.224";
        final int port = 37777;
        final String usrname = "admin";
        final String password = "admin";
        final NetSDKLib.NET_DEVICEINFO deviceInfo = new NetSDKLib.NET_DEVICEINFO();
        
        loginHandle = netsdkApi.CLIENT_LoginEx(address, (short)port, usrname, 
                password, nSpecCap, null, deviceInfo, error);
        if(loginHandle.longValue() == 0) {
            System.err.printf("Login Device [%s:%d] Failed ! Last Error[%x]\n", address, port, netsdkApi.CLIENT_GetLastError());
            return;
        }
 
        System.out.printf("Login Device [%s:%d] Success. \n", address, port);        
    }
    
    public static class SnapCallback implements NetSDKLib.fSnapRev {
        private static SnapCallback instance = new SnapCallback();
        private SnapCallback() {}
        public static SnapCallback getInstance() { 
            return instance;
        }
        
        public void invoke( LLong lLoginID, Pointer pBuf, int RevLen, int EncodeType, int CmdSerial, Pointer dwUser) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyMMddHHmmss");
            String fileName = "AsyncSnapPicture_" + dateFormat.format(new Date()) + "_" + CmdSerial + ".jpg";
            
            //保存图片到本地文件
            ToolKits.savePicture(pBuf, RevLen, fileName);
            System.out.println("--> Get Picture " + new File(fileName).getAbsolutePath());
                
            // 成功生成图片之后, 进行通知
            synchronized (SnapCallback.class) {
                SnapCallback.class.notify();
            }
        }
    }
    
    /**
     * 异步方式抓图 :适用于 IPC, 球机等非智能交通、停车场设备
     * 建议抓拍的频率不要超过1s
     */
    public synchronized void asyncSnapPicture() {
        if (loginHandle.longValue() == 0) {
            return;
        }
        /// 设置抓图回调: 图片主要在 SnapCallback.getInstance() invoke. 中返回
        netsdkApi.CLIENT_SetSnapRevCallBack(SnapCallback.getInstance(), null);
            
        NetSDKLib.SNAP_PARAMS snapParam = new NetSDKLib.SNAP_PARAMS();
        snapParam.Channel = 0; //抓图通道
        snapParam.mode = 0; //表示请求一帧 
        snapParam.CmdSerial = serialNum ++; // 请求序列号,有效值范围 0~65535,超过范围会被截断    
        
        /// 触发抓图动作
        if (!netsdkApi.CLIENT_SnapPictureEx(loginHandle, snapParam , null)) { 
            System.err.printf("CLIENT_SnapPictureEx Failed ! Last Error[%x]\n", netsdkApi.CLIENT_GetLastError());
            return;
        }
        
        // 以下保证图片数据的生成
        try {
            synchronized (SnapCallback.class) {
                SnapCallback.class.wait(3000L); // 默认等待3s, 防止设备断线时抓拍回调没有被触发,而导致死等
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("--> " + Thread.currentThread().getName() + " CLIENT_SnapPictureEx Success." + System.currentTimeMillis());
    }
    
    private int serialNum = 1;
    
    public void multiSnapPicture() {
        Thread[] threads = new Thread[5];
        for (Thread thread : threads) {
            thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    asyncSnapPicture();
                }
            });
            thread.start();
        }
    }
    
    /**
     * 同步方式抓图 , 建议抓拍的频率不要超过1s
     */
    public void syncSnapPicture() {
        
        NetSDKLib.NET_IN_SNAP_PIC_TO_FILE_PARAM snapParamIn = new NetSDKLib.NET_IN_SNAP_PIC_TO_FILE_PARAM();
        NetSDKLib.NET_OUT_SNAP_PIC_TO_FILE_PARAM snapParamOut = new NetSDKLib.NET_OUT_SNAP_PIC_TO_FILE_PARAM(1024 * 1024);
        
        snapParamIn.stuParam.Channel = 0;
        snapParamIn.stuParam.Quality = 3;
        snapParamIn.stuParam.ImageSize = 1; // 0:QCIF,1:CIF,2:D1
        snapParamIn.stuParam.mode = 0; // -1:表示停止抓图, 0:表示请求一帧, 1:表示定时发送请求, 2:表示连续请求
        snapParamIn.stuParam.InterSnap = 5;
        snapParamIn.stuParam.CmdSerial = serialNum;
        
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyMMddHHmmss");
        final String fileName = "SyncSnapPicture_" + dateFormat.format(new Date()) + "_" + serialNum + ".jpg";
        System.arraycopy(fileName.getBytes(), 0, snapParamIn.szFilePath, 0, fileName.getBytes().length);
        
        final int timeOut = 5000; // 5 second
 
 
        Pointer pInbuf =new Memory(snapParamIn.size());
        ToolKits.SetStructDataToPointer(snapParamIn, pInbuf, 0);
 
        Pointer pOutbuf =new Memory(snapParamOut.size());
        ToolKits.SetStructDataToPointer(snapParamOut, pOutbuf, 0);
 
        if (!netsdkApi.CLIENT_SnapPictureToFile(loginHandle, pInbuf, pOutbuf, timeOut)) {
            System.err.printf("CLIENT_SnapPictureEx Failed ! Last Error[%x]\n", netsdkApi.CLIENT_GetLastError());
            return;
        }
 
        ToolKits.GetPointerData(pOutbuf,snapParamOut);
 
 
        Pointer szPicBuf = snapParamOut.szPicBuf;
 
        byte[] byteArray = szPicBuf.getByteArray(0, snapParamOut.dwPicBufRetLen);
 
        System.out.println("CLIENT_SnapPictureToFile Success. " + new File(fileName).getAbsolutePath());
 
        // 图片下载完之后回收指针
        Native.free(Pointer.nativeValue(szPicBuf));
        Native.free(Pointer.nativeValue(pInbuf));
        Native.free(Pointer.nativeValue(pOutbuf));
    }
 
    @Override
    public void runTest() {
        System.out.println("Run Test");
        
        CaseMenu menu = new CaseMenu();
        menu.addItem(new CaseMenu.Item(this, "Async Snap picture.", "asyncSnapPicture"));
        menu.addItem(new CaseMenu.Item(this, "Mutil Snap picture.", "multiSnapPicture"));
        menu.addItem(new CaseMenu.Item(this, "Sync Snap picture.", "syncSnapPicture"));
        menu.run();
    }
 
    @Override
    public void endTest() {
        if( loginHandle.longValue() != 0) {
            netsdkApi.CLIENT_Logout(loginHandle);
            loginHandle.setValue(0);
        }
        
        /// 清理资源, 只需调用一次
        netsdkApi.CLIENT_Cleanup();
        
        System.out.println("See You...");
    }
    
    public static void main(String[] args) {
        SnapPicture demo = new SnapPicture();
        demo.initTest();
        demo.runTest();
        demo.endTest();
    }
}