-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdvr.cpp
215 lines (173 loc) · 6.07 KB
/
dvr.cpp
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
#include "dvr.h"
#include "utils.h"
#include "unistd.h"
#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <vector>
#include <chrono>
#include <thread>
namespace
{
void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)
{
std::cerr << "Got some exception: " << dwType << " for user: " << lUserID << " and handle: " << lHandle << std::endl;
}
void CALLBACK g_RealDataCallBack_V30(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void* dwUser)
{
// std::cout << "Got " << dwBufSize << " bytes: handle = " << lRealHandle << ", type = " << dwDataType << std::endl;
std::ofstream * out = static_cast<std::ofstream *>(dwUser);
switch (dwDataType)
{
case NET_DVR_STREAMDATA:
case NET_DVR_SYSHEAD:
{
const char * buf = reinterpret_cast<char *>(pBuffer);
out->write(buf, dwBufSize);
break;
}
}
}
}
namespace ASI
{
NET_DVR::NET_DVR(const char *ip, const WORD port, const std::string & username, const std::string & password) : myUserID(0), myDeviceInfo({0})
{
NET_DVR_USER_LOGIN_INFO loginInfo = {};
myDeviceInfo = {};
loginInfo.bUseAsynLogin = FALSE;
loginInfo.wPort = port;
strncpy(loginInfo.sDeviceAddress, ip, sizeof(loginInfo.sDeviceAddress) - 1);
strncpy(loginInfo.sUserName, username.c_str(), sizeof(loginInfo.sUserName) - 1);
strncpy(loginInfo.sPassword, password.c_str(), sizeof(loginInfo.sPassword) - 1);
myUserID = NET_DVR_Login_V40(&loginInfo, &myDeviceInfo);
if (myUserID < 0)
{
error("Login error");
}
}
NET_DVR::~NET_DVR()
{
const BOOL ok = NET_DVR_Logout(myUserID);
myUserID = 0;
if (!ok)
{
debug("NET_DVR_Logout");
}
}
void NET_DVR::info() const
{
const int firstChannel = myDeviceInfo.struDeviceV30.byStartDChan;
const int numberOfChannels = myDeviceInfo.struDeviceV30.byIPChanNum + myDeviceInfo.struDeviceV30.byHighDChanNum * 256;
std::cout << "First digital channel: " << firstChannel << std::endl;
std::cout << "Number of digital channels: " << numberOfChannels << std::endl;
}
[[ noreturn ]] void NET_DVR::error(const char * msg) const
{
LONG err = NET_DVR_GetLastError();
std::ostringstream ss;
ss << msg << ": " << err;
ss << " = " << NET_DVR_GetErrorMsg(&err);
throw std::runtime_error(ss.str());
}
void NET_DVR::debug(const char * msg) const
{
LONG err = NET_DVR_GetLastError();
std::ostringstream ss;
ss << msg << ": " << err;
ss << " = " << NET_DVR_GetErrorMsg(&err);
std::cerr << ss.str() << std::endl;
}
const NET_DVR_DEVICEINFO_V40 & NET_DVR::getDeviceInfo() const
{
return myDeviceInfo;
}
void NET_DVR::capturePicture(LONG channel, const std::string & filename) const
{
NET_DVR_JPEGPARA parameters = {};
/*
Apparently supported but not always working
AUTO = 0xff
CIF = 0 = 352x240
QCIF = 1 = 176x120
4CIF = 2 = 704x480
*/
parameters.wPicSize = 0xff;
parameters.wPicQuality = 2;
const LONG dChannel = myDeviceInfo.struDeviceV30.byStartDChan + channel;
const BOOL ok = NET_DVR_CaptureJPEGPicture(myUserID, dChannel, ¶meters, cast(filename));
if (!ok)
{
error("NET_DVR_CaptureJPEGPicture");
}
}
void NET_DVR::downloadFiles(const LONG channel, const std::tm & start, const std::tm & end, const std::string & filename) const
{
const LONG dChannel = myDeviceInfo.struDeviceV30.byStartDChan + channel;
NET_DVR_PLAYCOND downloadCond = {};
downloadCond.dwChannel = dChannel;
downloadCond.struStartTime.dwYear = 1900 + start.tm_year;
downloadCond.struStartTime.dwMonth = 1 + start.tm_mon;
downloadCond.struStartTime.dwDay = start.tm_mday;
downloadCond.struStartTime.dwHour = start.tm_hour;
downloadCond.struStartTime.dwMinute = start.tm_min;
downloadCond.struStartTime.dwSecond = start.tm_sec;
downloadCond.struStopTime.dwYear = 1900 + end.tm_year;
downloadCond.struStopTime.dwMonth = 1 + end.tm_mon;
downloadCond.struStopTime.dwDay = end.tm_mday;
downloadCond.struStopTime.dwHour = end.tm_hour;
downloadCond.struStopTime.dwMinute = end.tm_min;
downloadCond.struStopTime.dwSecond = end.tm_sec;
const LONG hPlayback = NET_DVR_GetFileByTime_V40(myUserID, cast(filename), &downloadCond);
if (hPlayback < 0)
{
error("NET_DVR_GetFileByTime_V40");
}
if (!NET_DVR_PlayBackControl_V40(hPlayback, NET_DVR_PLAYSTART, NULL, 0, NULL, NULL))
{
error("NET_DVR_PlayBackControl_V40");
}
std::cout << std::endl;
LONG pos = 0;
for (pos = 0; pos < 100 && pos >= 0; pos = NET_DVR_GetDownloadPos(hPlayback))
{
std::cout << "\rDownloading... " << pos << " %" << std::flush;
usleep(1000 * 200);
}
std::cout << std::endl;
if (!NET_DVR_StopGetFile(hPlayback))
{
error("NET_DVR_StopGetFile");
}
}
void NET_DVR::liveStream(const LONG channel, const int seconds, const std::string & filename) const
{
const LONG dChannel = myDeviceInfo.struDeviceV30.byStartDChan + channel;
NET_DVR_PREVIEWINFO struPlayInfo = {};
struPlayInfo.hPlayWnd = 0;
struPlayInfo.lChannel = dChannel;
struPlayInfo.dwStreamType = 0; //0-Main Stream, 1-Sub Stream, 2-Stream 3, 3-Stream 4, and so on
struPlayInfo.dwLinkMode = 0; //0- TCP Mode, 1- UDP Mode, 2- Multicast Mode, 3- RTP Mode, 4-RTP/RTSP, 5-RSTP/HTTP
struPlayInfo.bBlocked = 1; //0- Non-blocking Streaming, 1- Blocking Streaming
std::ofstream out(filename.c_str());
const LONG realPlayHandle = NET_DVR_RealPlay_V40(myUserID, &struPlayInfo, g_RealDataCallBack_V30, &out);
if (realPlayHandle < 0)
{
error("NET_DVR_RealPlay_V40");
}
std::this_thread::sleep_for(std::chrono::seconds(seconds));
NET_DVR_StopRealPlay(realPlayHandle);
out.flush();
}
NET_SDK::NET_SDK()
{
NET_DVR_Init();
NET_DVR_SetExceptionCallBack_V30(0, NULL, g_ExceptionCallBack, NULL);
}
NET_SDK::~NET_SDK()
{
NET_DVR_Cleanup();
}
}