UDPSocketCapture.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /* UDPSocketCapture.cpp/Open GoPro, Version 2.0 (C) Copyright 2021 GoPro, Inc. (http://gopro.com/OpenGoPro). */
  2. /* This copyright was auto-generated on Sat Mar 5 01:05:53 UTC 2022 */
  3. #include "UDPSocketCapture.h"
  4. #include "HTTPRequest.h"
  5. #include "GoProStreamDemo.h"
  6. #ifndef snprintf
  7. #define snprintf(buf,len, format,...) _snprintf_s(buf, len,len, format, __VA_ARGS__)
  8. #endif
  9. #define READ_BUFFER_SIZE 16384
  10. extern "C"
  11. {
  12. #include "demuxing_decoding.h"
  13. }
  14. #include "BufferNegotiator.h"
  15. UDPSocketCapture::UDPSocketCapture()
  16. {
  17. }
  18. UDPSocketCapture::~UDPSocketCapture()
  19. {
  20. Stop();
  21. }
  22. LONG GetStringRegKey(HKEY hKey, const std::string& strValueName, std::string& strValue)
  23. {
  24. CHAR szBuffer[512] = { 0 };
  25. DWORD dwBufferSize = sizeof(szBuffer);
  26. ULONG nError;
  27. nError = RegQueryValueExA(hKey, strValueName.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
  28. if (ERROR_SUCCESS == nError)
  29. {
  30. strValue = szBuffer;
  31. }
  32. return nError;
  33. }
  34. int UDPSocketCapture::FindCamera(std::string& address)
  35. {
  36. int ret = -1;
  37. address = "";
  38. WSAData wsaData;
  39. if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
  40. {
  41. return 255;
  42. }
  43. std::string myaddr = "";
  44. address = "";
  45. char logbuf[100] = { 0 };
  46. char ac[80];
  47. if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR)
  48. {
  49. snprintf(logbuf, 100, "Error %d when getting local host name.\n", WSAGetLastError());
  50. OutputDebugStringA(logbuf);
  51. WSACleanup();
  52. return -1;
  53. }
  54. snprintf(logbuf, 100, "Host name is %s\n", ac);
  55. OutputDebugStringA(logbuf);
  56. struct hostent* phe = gethostbyname(ac);
  57. struct addrinfo* result = NULL;
  58. struct addrinfo* res = NULL;
  59. getaddrinfo(ac, NULL, NULL, &result);
  60. if (phe == 0)
  61. {
  62. OutputDebugStringA("Bad host lookup.\n");
  63. WSACleanup();
  64. return -1;
  65. }
  66. for (int i = 0; phe->h_addr_list[i] != 0; ++i)
  67. {
  68. struct in_addr addr;
  69. memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr));
  70. snprintf(logbuf, 100, "Address %d: %s\n ", i , inet_ntoa(addr));
  71. OutputDebugStringA(logbuf);
  72. if ((int)addr.S_un.S_un_b.s_b1 == 172 && ((int)addr.S_un.S_un_b.s_b2 >= 20 && (int)addr.S_un.S_un_b.s_b2 <= 29) &&
  73. ((int)addr.S_un.S_un_b.s_b4 >= 50 && (int)addr.S_un.S_un_b.s_b4 <= 70))
  74. {
  75. address = inet_ntoa(addr);
  76. address.replace(address.length() - 1, 1, "1");
  77. ret = 0;
  78. }
  79. }
  80. WSACleanup();
  81. return ret;
  82. }
  83. void UDPSocketCapture::Start(int height)
  84. {
  85. if (!mStarted)
  86. {
  87. mHeight = height;
  88. this->mCaptureThread = std::thread(CaptureThread, this);
  89. this->mOutputThread = std::thread(OutputThread, this);
  90. mStarted = true;
  91. }
  92. }
  93. void UDPSocketCapture::Stop()
  94. {
  95. if (mStarted)
  96. {
  97. StopDecoding();
  98. StopCapture();
  99. mQuitNow = true;
  100. if (mCaptureThread.joinable())
  101. mCaptureThread.join();
  102. if(mOutputThread.joinable())
  103. mOutputThread.join();
  104. mStarted = false;
  105. }
  106. }
  107. void UDPSocketCapture::GetBuffer(uint8_t* buf, long bufsize, long& bytesReturned)
  108. {
  109. mBufMutex.lock();
  110. static size_t actualbytes = 0;
  111. if (buf == NULL || bufsize == 0)
  112. {
  113. mBufMutex.unlock();
  114. return;
  115. }
  116. bytesReturned = ::GetBuffer(buf, bufsize);
  117. if (bytesReturned == 0)
  118. {
  119. if (mBigBuf == NULL)
  120. {
  121. char path[MAX_PATH];
  122. std::string spath = "";
  123. HMODULE hm = NULL;
  124. if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
  125. GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
  126. (LPCSTR)&GetStringRegKey, &hm) == 0)
  127. {
  128. int err = GetLastError();
  129. fprintf(stderr, "GetModuleHandle failed, error = %d\n", err);
  130. }
  131. if (GetModuleFileNameA(hm, path, sizeof(path)) == 0)
  132. {
  133. int err = GetLastError();
  134. fprintf(stderr, "GetModuleFileName failed, error = %d\n", err);
  135. }
  136. spath = path;
  137. size_t slashpos = spath.find_last_of("\\", spath.length()) + 1;
  138. #ifdef USE_PREVIEW_STREAM
  139. spath.replace(slashpos, spath.length() - slashpos, "raw720.img");
  140. #else
  141. spath.replace(slashpos, spath.length() - slashpos, "raw.img");
  142. #endif
  143. mBigBuf = (uint8_t*)malloc(BIG_BUF_SIZE);
  144. if (mBigBuf != NULL)
  145. {
  146. FILE* ou = fopen(spath.c_str(), "rb");
  147. if (ou)
  148. {
  149. actualbytes = fread(mBigBuf, 1, BIG_BUF_SIZE, ou);
  150. fclose(ou);
  151. bytesReturned = actualbytes;
  152. }
  153. else
  154. {
  155. free(mBigBuf);
  156. mBigBuf = NULL;
  157. }
  158. }
  159. }
  160. if (mBigBuf != NULL)
  161. {
  162. if (bufsize!=0 && bufsize >= actualbytes)
  163. {
  164. memcpy(buf, mBigBuf, actualbytes);
  165. bytesReturned = actualbytes;
  166. }
  167. }
  168. }
  169. mBufMutex.unlock();
  170. }
  171. void UDPSocketCapture::WriteBuffer(uint8_t* buf, int bufsize)
  172. {
  173. mBufMutex.lock();
  174. mBufMutex.unlock();
  175. }
  176. /*
  177. This function is responsible for calling decode on the captured buffer
  178. */
  179. void UDPSocketCapture::OutputThread(UDPSocketCapture* me)
  180. {
  181. std::string addr = "";
  182. while (FindCamera(addr) != 0 && !me->mQuitNow)
  183. {
  184. Sleep(500);
  185. }
  186. if (!me->mQuitNow)
  187. {
  188. bool alreadyStarted = false;
  189. {
  190. HTTPRequest req(addr, 8080);
  191. if (req.get_request("/gopro/webcam/status"))
  192. {
  193. std::string stat = req.get_response();
  194. std::string findme = "\"status\": 2";
  195. if (stat.find(findme, 0) != std::string::npos)
  196. alreadyStarted = true;
  197. }
  198. if (alreadyStarted)
  199. {
  200. HTTPRequest req(addr, 8080);
  201. if (req.get_request("/gopro/webcam/stop"))
  202. {
  203. std::string stat = req.get_response();
  204. }
  205. Sleep(200);
  206. }
  207. }
  208. {
  209. HTTPRequest req(addr, 8080);
  210. #ifdef USE_PREVIEW_STREAM
  211. std::string startaddr = "/gopro/camera/stream/start";
  212. #else
  213. std::string startaddr = "/gopro/webcam/start?res=%d&fov=0";
  214. #endif
  215. char bufff[256] = { 0 };
  216. int parm = 12;
  217. if(me->mHeight == 720)
  218. {
  219. parm = 7;
  220. }
  221. snprintf(bufff, 256, startaddr.c_str(), parm);
  222. std::string buf = bufff;
  223. if (req.get_request(buf))
  224. {
  225. std::string stat = req.get_response();
  226. }
  227. }
  228. const char* url = "udp://@0.0.0.0:8554";
  229. while (!me->mQuitNow)
  230. {
  231. try
  232. {
  233. DecodeStream();
  234. }
  235. catch (...)
  236. {
  237. OutputDebugStringA("Decode crashed, quitting everything\n");
  238. }
  239. }
  240. {
  241. HTTPRequest req(addr, 8080);
  242. #ifdef USE_PREVIEW_STREAM
  243. req.get_request("/gopro/camera/stream/stop");
  244. #else
  245. req.get_request("/gopro/webcam/stop");
  246. if (!req.TimedOut)
  247. {
  248. HTTPRequest req2(addr, 8080);
  249. req2.get_request("/gopro/webcam/exit");
  250. }
  251. #endif
  252. }
  253. }
  254. OutputDebugStringA("LEAVING THREAD\n");
  255. }
  256. /*
  257. This is the main function that captures TS data from the camera and saves it to a buffer
  258. */
  259. void UDPSocketCapture::CaptureThread(UDPSocketCapture* me)
  260. {
  261. WSASession session;
  262. char buf[READ_BUFFER_SIZE] = { 0 };
  263. OutputDebugStringA("Starting receive thread\n");
  264. UDPSocket* mysock = new UDPSocket();
  265. mysock->Bind(8554);
  266. while (true)
  267. {
  268. if (mysock == NULL)
  269. {
  270. mysock = new UDPSocket();
  271. mysock->Bind(8554);
  272. }
  273. int received = 0;
  274. sockaddr_in blop = mysock->RecvFrom(buf, READ_BUFFER_SIZE, received);
  275. //LOGF::Instance()->LOG("Received %d bytes\n", received);
  276. if (received == READ_BUFFER_SIZE)
  277. OutputDebugStringA("Maxed out the buffer\n");
  278. if (received == 1 || me->mQuitNow)
  279. {
  280. //fclose(myfile);
  281. break;
  282. }
  283. WriteInputBuffer((uint8_t*)buf, received);
  284. memset(buf, 0, READ_BUFFER_SIZE);
  285. }
  286. }
  287. void UDPSocketCapture::StopCapture()
  288. {
  289. UDPSocket soc;
  290. char buf = 'q';
  291. soc.SendTo("127.0.0.1", 8554, &buf, 1);
  292. StopInput();
  293. }