WindowThread.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. #include "stdafx.h"
  2. #include <thread>
  3. #include <mutex>
  4. #include <memory>
  5. #include <math.h>
  6. #include "api.h"
  7. #include "Protocol.pb.h"
  8. #include "../common/peer_connection.h"
  9. #include "../common/socket_client.h"
  10. #include "../common/iobuffer.h"
  11. #include "WindowThread.h"
  12. #include "MultiMonitorEnumerator.h"
  13. #include "libyuv/convert_argb.h"
  14. #include "libyuv/rotate.h"
  15. #define PI 3.141526f
  16. CThreadWindow::CThreadWindow( RenderPosition pos,SocketClient * c): m_Pos(pos),m_Client(c)
  17. {
  18. start_ = false;
  19. _control = ControlState::Check;
  20. //bDataChannelCreated = false;
  21. }
  22. void CThreadWindow::Start()
  23. {
  24. m_Thread = std::thread(&CThreadWindow::Run, this);
  25. }
  26. void CThreadWindow::Run()
  27. {
  28. m_bRun = true;
  29. WNDCLASSEX wcex;
  30. wcex.cbSize = sizeof(WNDCLASSEX);
  31. wcex.style = CS_HREDRAW | CS_VREDRAW;
  32. wcex.lpfnWndProc = CThreadWindow::WndProc;
  33. wcex.cbClsExtra = 0;
  34. wcex.cbWndExtra = 0;
  35. wcex.hInstance = GetModuleHandle(nullptr);
  36. wcex.hIcon = 0;
  37. wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
  38. wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  39. wcex.lpszMenuName = NULL;
  40. char cName[MAX_PATH] = { 0 };
  41. GetModuleFileNameA(wcex.hInstance, cName, sizeof(cName));
  42. char* szApp = strrchr(cName, '\\') + 1;
  43. strchr(szApp, '.')[0] = '\0';
  44. wcex.lpszClassName = szApp;
  45. wcex.hIconSm = 0;
  46. RegisterClassEx(&wcex);
  47. CMultiMonitorEnumerator Enumerator;
  48. if(Enumerator.m_iMontorNumber !=3 )
  49. m_hWnd= CreateWindow(szApp, nullptr, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 0, 0, 1280, 720, NULL, NULL, wcex.hInstance, 0);
  50. else
  51. m_hWnd= CreateWindow(szApp, nullptr, WS_POPUP, 0, 0, 1024, 768, NULL, NULL, wcex.hInstance, 0);
  52. SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);
  53. ShowWindow(m_hWnd,SW_SHOW);
  54. UpdateWindow(m_hWnd);
  55. switch (m_Pos)
  56. {
  57. case RenderPosition::FRONT_BACK:
  58. {
  59. // CMultiMonitorEnumerator::VMONITORINFO* pvInfo = &Enumerator.m_MonitorInfoExArray[2];
  60. ::SetWindowTextW(m_hWnd, L"前视图");
  61. //if (Enumerator.m_iMontorNumber == 3)
  62. {
  63. //::MoveWindow(m_hWnd, pvInfo->rcMonitor.left, pvInfo->rcMonitor.top, 1920, 1280, true);
  64. }
  65. }
  66. break;
  67. case RenderPosition::LEFT:
  68. {
  69. // CMultiMonitorEnumerator::VMONITORINFO* pvInfo = &Enumerator.m_MonitorInfoExArray[0];
  70. ::SetWindowTextW(m_hWnd, L"左视图");
  71. // ::MoveWindow(m_hWnd, pvInfo->rcMonitor.left + 1152, pvInfo->rcMonitor.top, 768, 1024, true);
  72. }
  73. break;
  74. case RenderPosition::RIGHT:
  75. {
  76. // CMultiMonitorEnumerator::VMONITORINFO* pvInfo = &Enumerator.m_MonitorInfoExArray[1];
  77. ::SetWindowTextW(m_hWnd, L"右视图");
  78. // ::MoveWindow(m_hWnd, pvInfo->rcMonitor.left, pvInfo->rcMonitor.top, 768, 1024, true);
  79. }
  80. break;
  81. }
  82. MSG msg;
  83. while (GetMessage(&msg, nullptr, 0, 0))
  84. {
  85. if(msg.message==WM_DESTROY) break;
  86. TranslateMessage(&msg);
  87. DispatchMessage(&msg);
  88. }
  89. }
  90. LRESULT CThreadWindow::WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  91. {
  92. switch (wMsg)
  93. {
  94. case WM_PAINT:
  95. {
  96. CThreadWindow* lThis = (CThreadWindow*)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  97. if (lThis != nullptr)
  98. {
  99. lThis->OnPaint(hWnd);
  100. return 1;
  101. }
  102. }
  103. break;
  104. case WM_NOTIFY_REP:
  105. {
  106. CThreadWindow* lThis =(CThreadWindow *)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  107. lThis-> OnVideoRep((int32_t)wParam);
  108. }
  109. break;
  110. case WM_NOTIFY_ANSWER:
  111. {
  112. CThreadWindow* lThis = (CThreadWindow*)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  113. lThis->OnVideoAnswer((CIOBuffer*)wParam);
  114. }
  115. break;
  116. case WM_NOTIFY_CANDIDATE:
  117. {
  118. CThreadWindow* lThis = (CThreadWindow*)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  119. lThis->OnVideoCandidate((CIOBuffer*)wParam);
  120. }
  121. break;
  122. case WM_NOTIFY_OFFER:
  123. {
  124. CThreadWindow* lThis = (CThreadWindow*)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  125. lThis->OnVideoOffer((CIOBuffer*)wParam);
  126. }
  127. break;
  128. //case WM_ERASEBKGND:
  129. //{
  130. // return 1;
  131. //}
  132. //break;
  133. case WM_NOTIFY_LEAVE:
  134. {
  135. CThreadWindow * lThis= (CThreadWindow*)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  136. lThis->OnVideoLeave();
  137. }
  138. break;
  139. case WM_DESTROY:
  140. PostQuitMessage(0);
  141. break;
  142. }
  143. return DefWindowProc(hWnd, wMsg, wParam, lParam);
  144. }
  145. void CThreadWindow::Stop()
  146. {
  147. PostMessage(WM_DESTROY, 0, 0);
  148. m_Thread.join();
  149. }
  150. void CThreadWindow::PostMessage(UINT wMsg, WPARAM wParam, LPARAM lParam)
  151. {
  152. ::PostMessage(m_hWnd, wMsg, wParam, lParam);
  153. }
  154. void CThreadWindow::OnVideoRep(int32_t peer)
  155. {
  156. int32_t width = 1280;
  157. int32_t height = 720;
  158. //auto type = m_Pos < RenderPosition::CAR_FRONT ? EgoType::Cave : EgoType::Car;
  159. m_PeerConnection = std::make_unique<CPeerConnection>((ChannelType)m_Pos, m_Client);
  160. //m_VideoRender = std::make_unique<CVideoRenderer>();
  161. SetRenderWindow(width, height);
  162. InitPeerConnection(peer);
  163. m_PeerConnection->CreateOffer();
  164. }
  165. void CThreadWindow::OnVideoLeave()
  166. {
  167. if (!start_) return;
  168. start_ = false;
  169. //bDataChannelCreated = false;
  170. m_Peer = -1;
  171. m_PeerConnection->Close();
  172. m_PeerConnection.reset();
  173. m_PeerConnection = nullptr;
  174. image_ = nullptr;
  175. ::InvalidateRect(m_hWnd, NULL, TRUE);
  176. }
  177. void CThreadWindow::InitPeerConnection(int32_t peer)
  178. {
  179. m_PeerConnection->Initialize(peer, m_Pos);
  180. m_PeerConnection->AddDataChannel(true, false);
  181. m_PeerConnection->AddRemoteArgb32VideoFrameReady(&CThreadWindow::FrameCallback, this);
  182. StartRender(true);
  183. }
  184. void CThreadWindow::SetPeer(int32_t peer)
  185. {
  186. m_Peer = peer;
  187. }
  188. void CThreadWindow::CreateVideoReq()
  189. {
  190. //auto type = m_Pos < CameraPosition::CAR_FRONT ? EgoType::Cave : EgoType::Car;
  191. m_Client->WriteVideoReq(m_Peer, m_Pos);
  192. }
  193. void CThreadWindow::OnVideoAnswer(CIOBuffer* pBuffer)
  194. {
  195. AnswerDesc* desc = (AnswerDesc*)pBuffer->Buffer;
  196. const char* type = desc->type;
  197. const char* sdp = desc->sdp;
  198. m_PeerConnection->SetRemoteDescription(type, sdp);
  199. pBuffer->Release();
  200. }
  201. void CThreadWindow::OnVideoCandidate(CIOBuffer* pBuffer)
  202. {
  203. CandidateDesc* desc = (CandidateDesc*)pBuffer->Buffer;
  204. auto candidate = desc->candidate;
  205. auto sdp_mid = desc->sdp_mid;
  206. auto sdp_mline_index = desc->sdp_mline_index;
  207. m_PeerConnection->AddIceCandidate(candidate, sdp_mline_index, sdp_mid);
  208. pBuffer->Release();
  209. }
  210. void CThreadWindow::OnVideoOffer(CIOBuffer* pBuffer)
  211. {
  212. OfferDesc* desc = (OfferDesc*)pBuffer->Buffer;
  213. auto type = desc->type;
  214. auto sdp = desc->sdp;
  215. m_PeerConnection->SetRemoteDescription(type, sdp);
  216. m_PeerConnection->CreateAnswer();
  217. pBuffer->Release();
  218. }
  219. /*
  220. void CThreadWindow::WriteCanMessage(std::unordered_map<int32_t, cannet_frame>& node,bool)
  221. {
  222. if (bDataChannelCreated == false||node.empty()) return;
  223. RemoNet::CCCanMesage Req;
  224. Req.set_islidar(false);
  225. for (auto& it:node)
  226. {
  227. // if (it.second.canid == htonl(0x486))
  228. {
  229. auto m = Req.add_message();
  230. m->set_head(it.second.header);
  231. m->set_canid(it.second.canid);
  232. m->set_data(it.second.data, 8);
  233. // m->set_islidar(false);
  234. }
  235. // it->second.canid
  236. }
  237. MessageHead Head;
  238. CIOBuffer pBuffer;
  239. Head.Command = RemoNet::CC_CAN;
  240. Head.Length = Req.ByteSizeLong();
  241. Head.Serialize(pBuffer.Buffer);
  242. auto ptr = pBuffer.Buffer + MessageHead::Size();
  243. Req.SerializeToArray(ptr, Head.Length);
  244. pBuffer.Length = MessageHead::Size() + Head.Length;
  245. m_PeerConnection->SendData(&pBuffer);
  246. }
  247. */
  248. void CThreadWindow::SetRenderWindow(int32_t width, int32_t height)
  249. {
  250. ZeroMemory(&bmi_, sizeof(bmi_));
  251. bmi_.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  252. bmi_.bmiHeader.biPlanes = 1;
  253. bmi_.bmiHeader.biBitCount = 32;
  254. bmi_.bmiHeader.biCompression = BI_RGB;
  255. if (m_Pos == RenderPosition::LEFT || m_Pos == RenderPosition::RIGHT)
  256. {
  257. bmi_.bmiHeader.biWidth = height;
  258. bmi_.bmiHeader.biHeight = -width;
  259. }
  260. else{
  261. bmi_.bmiHeader.biWidth = width;
  262. bmi_.bmiHeader.biHeight = -height;
  263. }
  264. bmi_.bmiHeader.biSizeImage =
  265. width * height * (bmi_.bmiHeader.biBitCount >> 3);
  266. image_.reset(new uint8_t[bmi_.bmiHeader.biSizeImage]);
  267. if(m_Pos==RenderPosition::LEFT||m_Pos== RenderPosition::RIGHT)
  268. _rotate.reset(new uint8_t[bmi_.bmiHeader.biSizeImage]);
  269. }
  270. void CThreadWindow::FrameCallback(void* user_data,
  271. const uint8_t* yptr, int32_t strideY,
  272. const uint8_t* uptr, int32_t strideU,
  273. const uint8_t* vptr, int32_t strideV,
  274. const int32_t stride, const int frame_width,
  275. const int frame_height)
  276. {
  277. auto ptr = static_cast<CThreadWindow*>(user_data);
  278. ptr->OnArgb32FrameReady(yptr, strideY, uptr,strideU,vptr,strideV,stride, frame_width, frame_height);
  279. }
  280. void CThreadWindow::StartRender(bool b)
  281. {
  282. start_ = b;
  283. }
  284. void CThreadWindow::OnPaint(HWND hWnd)
  285. {
  286. PAINTSTRUCT ps;
  287. HDC hdc = BeginPaint(hWnd, &ps);
  288. // TODO: Add any drawing code that uses hdc here...
  289. if (start_)
  290. {
  291. RECT rc;
  292. ::GetClientRect(hWnd, &rc);
  293. //const uint8_t* image =
  294. //AutoLock<VideoRenderer> local_lock(renderer);
  295. //const BITMAPINFO& bmi = renderer->bmi();
  296. // std::lock_guard < std::mutex> l(buffer_lock_);
  297. int height = abs(bmi_.bmiHeader.biHeight);
  298. int width = bmi_.bmiHeader.biWidth;
  299. HDC dc_mem = ::CreateCompatibleDC(ps.hdc);
  300. ::SetStretchBltMode(dc_mem, HALFTONE);
  301. HDC all_dc[] = { ps.hdc, dc_mem };
  302. for (size_t i = 0; i < _countof(all_dc); ++i) {
  303. SetMapMode(all_dc[i], MM_ISOTROPIC);
  304. SetWindowExtEx(all_dc[i], width, height, NULL);
  305. SetViewportExtEx(all_dc[i], rc.right, rc.bottom, NULL);
  306. }
  307. HBITMAP bmp_mem = ::CreateCompatibleBitmap(ps.hdc, rc.right, rc.bottom);
  308. HGDIOBJ bmp_old = ::SelectObject(dc_mem, bmp_mem);
  309. POINT logical_area = { rc.right, rc.bottom };
  310. DPtoLP(ps.hdc, &logical_area, 1);
  311. HBRUSH brush = ::CreateSolidBrush(RGB(0, 0, 0));
  312. RECT logical_rect = { 0, 0, logical_area.x, logical_area.y };
  313. ::FillRect(dc_mem, &logical_rect, brush);
  314. ::DeleteObject(brush);
  315. int x = (logical_area.x / 2) - (width / 2);
  316. int y = (logical_area.y / 2) - (height / 2);
  317. StretchDIBits(dc_mem, x, y, width, height, 0, 0, width, height, image_.get(),
  318. &bmi_, DIB_RGB_COLORS, SRCCOPY);
  319. BitBlt(ps.hdc, 0, 0, logical_area.x, logical_area.y, dc_mem, 0, 0,
  320. SRCCOPY);
  321. // Cleanup.
  322. ::SelectObject(dc_mem, bmp_old);
  323. ::DeleteObject(bmp_mem);
  324. ::DeleteDC(dc_mem);
  325. }
  326. EndPaint(hWnd, &ps);
  327. }
  328. void CThreadWindow::OnArgb32FrameReady(const uint8_t* yptr,int32_t strideY, const uint8_t* uptr,int32_t strideU, const uint8_t* vptr,int32_t strideV, const int32_t stride,const int width, const int height)
  329. {
  330. {
  331. // int32_t*pixels = (int32_t*)data;
  332. //std::lock_guard < std::mutex> l(buffer_lock_);
  333. if (RenderPosition::LEFT == m_Pos)
  334. {
  335. SetSize(height,width);
  336. uint8_t* i420_image_rotated = _rotate.get();////(uint8_t*)malloc(width * height * 3 ) ;
  337. uint8_t* i420_image_rotated_y_ptr = i420_image_rotated;
  338. uint8_t* i420_image_rotated_u_ptr = i420_image_rotated_y_ptr + (height * width);
  339. uint8_t* i420_image_rotated_v_ptr = i420_image_rotated_u_ptr + (int)(height * width * 0.25);
  340. libyuv::I420Rotate(yptr, width, uptr, width>>1, vptr, width>>1, i420_image_rotated_y_ptr,
  341. height,
  342. i420_image_rotated_u_ptr,
  343. height >>1,
  344. i420_image_rotated_v_ptr,
  345. height >>1,
  346. width,
  347. height, libyuv::RotationMode::kRotate270);
  348. yptr = i420_image_rotated_y_ptr;
  349. strideY = height;
  350. uptr = i420_image_rotated_u_ptr;
  351. strideU = height >> 1;
  352. vptr = i420_image_rotated_v_ptr;
  353. strideV = height >> 1;
  354. libyuv::I420ToARGB(yptr, strideY, uptr, strideU, vptr, strideV, image_.get(), height*4, height, width );
  355. }
  356. else if (RenderPosition::RIGHT == m_Pos)
  357. {
  358. SetSize(height, width);
  359. uint8_t* i420_image_rotated = _rotate.get();
  360. uint8_t* i420_image_rotated_y_ptr = i420_image_rotated;
  361. uint8_t* i420_image_rotated_u_ptr = i420_image_rotated_y_ptr + (height * width);
  362. uint8_t* i420_image_rotated_v_ptr = i420_image_rotated_u_ptr + (int)(height * width * 0.25);
  363. libyuv::I420Rotate(yptr, width, uptr, width >> 1, vptr, width >> 1, i420_image_rotated_y_ptr,
  364. height,
  365. i420_image_rotated_u_ptr,
  366. height >> 1,
  367. i420_image_rotated_v_ptr,
  368. height >> 1,
  369. width,
  370. height, libyuv::RotationMode::kRotate90);
  371. yptr = i420_image_rotated_y_ptr;
  372. strideY = height;
  373. uptr = i420_image_rotated_u_ptr;
  374. strideU = height >> 1;
  375. vptr = i420_image_rotated_v_ptr;
  376. strideV = height >> 1;
  377. libyuv::I420ToARGB(yptr, strideY, uptr, strideU, vptr, strideV, image_.get(), height * 4, height, width);
  378. }
  379. else
  380. {
  381. SetSize(width,height);
  382. libyuv::I420ToARGB(yptr, strideY, uptr, strideU, vptr, strideV, image_.get(), stride, width, height);
  383. }
  384. }
  385. ::InvalidateRect(m_hWnd, NULL, FALSE);
  386. }
  387. void CThreadWindow::SetSize(int32_t width, int32_t height)
  388. {
  389. if (width == bmi_.bmiHeader.biWidth && height == -bmi_.bmiHeader.biHeight) {
  390. return;
  391. }
  392. // if (m_Pos == CameraPosition::CAR_LEFT || m_Pos == CameraPosition::CAR_RIGHT)
  393. // {
  394. // bmi_.bmiHeader.biWidth = height;
  395. // bmi_.bmiHeader.biHeight = -width;
  396. // }
  397. // else
  398. {
  399. bmi_.bmiHeader.biWidth = width;
  400. bmi_.bmiHeader.biHeight = -height;
  401. }
  402. bmi_.bmiHeader.biSizeImage =
  403. width * height * (bmi_.bmiHeader.biBitCount >> 3);
  404. image_.reset(new uint8_t[bmi_.bmiHeader.biSizeImage]);
  405. if (m_Pos == RenderPosition::LEFT || m_Pos == RenderPosition::RIGHT)
  406. _rotate.reset(new uint8_t[bmi_.bmiHeader.biSizeImage]);
  407. }
  408. void CThreadWindow::DelayNextVideoReq()
  409. {
  410. m_DelayThread = std::thread(&CThreadWindow::AskVideoReq, this);
  411. m_DelayThread.detach();
  412. }
  413. void CThreadWindow::DelayDataChannel()
  414. {
  415. m_DelayThread = std::thread(&CThreadWindow::AskDataChannel, this);
  416. m_DelayThread.detach();
  417. }
  418. void CThreadWindow::AskVideoReq()
  419. {
  420. Sleep(1000);
  421. m_Client->WriteVideoReq(m_Peer, m_Pos);
  422. }
  423. void CThreadWindow::AskDataChannel()
  424. {
  425. Sleep(1000);
  426. //bDataChannelCreated = true;
  427. RemoNet::CCAskDataChannel Req;
  428. m_PeerConnection->SetDataReady();
  429. CIOBuffer Buffer;
  430. MessageHead Head;
  431. Head.Command = RemoNet::CC_ASKDATACHANNEL;
  432. Head.Length = Req.ByteSize();
  433. Head.Serialize(Buffer.Buffer);
  434. auto ptr = Buffer.Buffer + MessageHead::Size();
  435. Req.SerializeToArray(ptr, Head.Length);
  436. Buffer.Length = Head.Length + MessageHead::Size();
  437. SendData(&Buffer);
  438. }
  439. void CThreadWindow::SendData(CIOBuffer* pBuffer)
  440. {
  441. m_PeerConnection->SendData(pBuffer);
  442. }
  443. ControlState CThreadWindow::GetControlState()
  444. {
  445. return _control;
  446. }
  447. /*
  448. void CThreadWindow::Notify(int8_t* buffer, int32_t size)
  449. {
  450. }
  451. void CThreadWindow::SetCanSocket(SocketCan* can)
  452. {
  453. }
  454. */