WindowThread.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  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. case RenderPosition::DASHBOARD:
  82. {
  83. // CMultiMonitorEnumerator::VMONITORINFO* pvInfo = &Enumerator.m_MonitorInfoExArray[1];
  84. ::SetWindowTextW(m_hWnd, L"仪表盘");
  85. // ::MoveWindow(m_hWnd, pvInfo->rcMonitor.left, pvInfo->rcMonitor.top, 768, 1024, true);
  86. }
  87. break;
  88. }
  89. MSG msg;
  90. while (GetMessage(&msg, nullptr, 0, 0))
  91. {
  92. if(msg.message==WM_DESTROY) break;
  93. TranslateMessage(&msg);
  94. DispatchMessage(&msg);
  95. }
  96. }
  97. LRESULT CThreadWindow::WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  98. {
  99. switch (wMsg)
  100. {
  101. case WM_PAINT:
  102. {
  103. CThreadWindow* lThis = (CThreadWindow*)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  104. if (lThis != nullptr)
  105. {
  106. lThis->OnPaint(hWnd);
  107. return 1;
  108. }
  109. }
  110. break;
  111. case WM_NOTIFY_REP:
  112. {
  113. CThreadWindow* lThis =(CThreadWindow *)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  114. lThis-> OnVideoRep((int32_t)wParam);
  115. }
  116. break;
  117. case WM_NOTIFY_ANSWER:
  118. {
  119. CThreadWindow* lThis = (CThreadWindow*)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  120. lThis->OnVideoAnswer((CIOBuffer*)wParam);
  121. }
  122. break;
  123. case WM_NOTIFY_CANDIDATE:
  124. {
  125. CThreadWindow* lThis = (CThreadWindow*)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  126. lThis->OnVideoCandidate((CIOBuffer*)wParam);
  127. }
  128. break;
  129. case WM_NOTIFY_OFFER:
  130. {
  131. CThreadWindow* lThis = (CThreadWindow*)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  132. lThis->OnVideoOffer((CIOBuffer*)wParam);
  133. }
  134. break;
  135. //case WM_ERASEBKGND:
  136. //{
  137. // return 1;
  138. //}
  139. //break;
  140. case WM_NOTIFY_LEAVE:
  141. {
  142. CThreadWindow * lThis= (CThreadWindow*)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  143. lThis->OnVideoLeave();
  144. }
  145. break;
  146. case WM_DESTROY:
  147. PostQuitMessage(0);
  148. break;
  149. }
  150. return DefWindowProc(hWnd, wMsg, wParam, lParam);
  151. }
  152. void CThreadWindow::Stop()
  153. {
  154. PostMessage(WM_DESTROY, 0, 0);
  155. m_Thread.join();
  156. }
  157. void CThreadWindow::PostMessage(UINT wMsg, WPARAM wParam, LPARAM lParam)
  158. {
  159. ::PostMessage(m_hWnd, wMsg, wParam, lParam);
  160. }
  161. void CThreadWindow::OnVideoRep(int32_t peer)
  162. {
  163. int32_t width = 1280;
  164. int32_t height = 720;
  165. //auto type = m_Pos < RenderPosition::CAR_FRONT ? EgoType::Cave : EgoType::Car;
  166. m_PeerConnection = std::make_unique<CPeerConnection>((ChannelType)m_Pos, m_Client);
  167. //m_VideoRender = std::make_unique<CVideoRenderer>();
  168. SetRenderWindow(width, height);
  169. InitPeerConnection(peer);
  170. m_PeerConnection->CreateOffer();
  171. }
  172. void CThreadWindow::OnVideoLeave()
  173. {
  174. if (!start_) return;
  175. start_ = false;
  176. _control = ControlState::Check;
  177. //bDataChannelCreated = false;
  178. m_Peer = -1;
  179. m_PeerConnection->Close();
  180. m_PeerConnection.reset();
  181. m_PeerConnection = nullptr;
  182. image_ = nullptr;
  183. ::InvalidateRect(m_hWnd, NULL, TRUE);
  184. }
  185. void CThreadWindow::InitPeerConnection(int32_t peer)
  186. {
  187. m_PeerConnection->Initialize(peer, m_Pos);
  188. m_PeerConnection->AddDataChannel(true, false);
  189. m_PeerConnection->AddRemoteArgb32VideoFrameReady(&CThreadWindow::FrameCallback, this);
  190. StartRender(true);
  191. }
  192. void CThreadWindow::SetPeer(int32_t peer)
  193. {
  194. m_Peer = peer;
  195. }
  196. void CThreadWindow::CreateVideoReq()
  197. {
  198. //auto type = m_Pos < CameraPosition::CAR_FRONT ? EgoType::Cave : EgoType::Car;
  199. m_Client->WriteVideoReq(m_Peer, m_Pos);
  200. }
  201. void CThreadWindow::OnVideoAnswer(CIOBuffer* pBuffer)
  202. {
  203. AnswerDesc* desc = (AnswerDesc*)pBuffer->Buffer;
  204. const char* type = desc->type;
  205. const char* sdp = desc->sdp;
  206. m_PeerConnection->SetRemoteDescription(type, sdp);
  207. pBuffer->Release();
  208. }
  209. void CThreadWindow::OnVideoCandidate(CIOBuffer* pBuffer)
  210. {
  211. CandidateDesc* desc = (CandidateDesc*)pBuffer->Buffer;
  212. auto candidate = desc->candidate;
  213. auto sdp_mid = desc->sdp_mid;
  214. auto sdp_mline_index = desc->sdp_mline_index;
  215. m_PeerConnection->AddIceCandidate(candidate, sdp_mline_index, sdp_mid);
  216. pBuffer->Release();
  217. }
  218. void CThreadWindow::OnVideoOffer(CIOBuffer* pBuffer)
  219. {
  220. OfferDesc* desc = (OfferDesc*)pBuffer->Buffer;
  221. auto type = desc->type;
  222. auto sdp = desc->sdp;
  223. m_PeerConnection->SetRemoteDescription(type, sdp);
  224. m_PeerConnection->CreateAnswer();
  225. pBuffer->Release();
  226. }
  227. /*
  228. void CThreadWindow::WriteCanMessage(std::unordered_map<int32_t, cannet_frame>& node,bool)
  229. {
  230. if (bDataChannelCreated == false||node.empty()) return;
  231. RemoNet::CCCanMesage Req;
  232. Req.set_islidar(false);
  233. for (auto& it:node)
  234. {
  235. // if (it.second.canid == htonl(0x486))
  236. {
  237. auto m = Req.add_message();
  238. m->set_head(it.second.header);
  239. m->set_canid(it.second.canid);
  240. m->set_data(it.second.data, 8);
  241. // m->set_islidar(false);
  242. }
  243. // it->second.canid
  244. }
  245. MessageHead Head;
  246. CIOBuffer pBuffer;
  247. Head.Command = RemoNet::CC_CAN;
  248. Head.Length = Req.ByteSizeLong();
  249. Head.Serialize(pBuffer.Buffer);
  250. auto ptr = pBuffer.Buffer + MessageHead::Size();
  251. Req.SerializeToArray(ptr, Head.Length);
  252. pBuffer.Length = MessageHead::Size() + Head.Length;
  253. m_PeerConnection->SendData(&pBuffer);
  254. }
  255. */
  256. void CThreadWindow::SetRenderWindow(int32_t width, int32_t height)
  257. {
  258. ZeroMemory(&bmi_, sizeof(bmi_));
  259. bmi_.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  260. bmi_.bmiHeader.biPlanes = 1;
  261. bmi_.bmiHeader.biBitCount = 32;
  262. bmi_.bmiHeader.biCompression = BI_RGB;
  263. if (m_Pos == RenderPosition::LEFT || m_Pos == RenderPosition::RIGHT)
  264. {
  265. bmi_.bmiHeader.biWidth = height;
  266. bmi_.bmiHeader.biHeight = -width;
  267. }
  268. else{
  269. bmi_.bmiHeader.biWidth = width;
  270. bmi_.bmiHeader.biHeight = -height;
  271. }
  272. bmi_.bmiHeader.biSizeImage =
  273. width * height * (bmi_.bmiHeader.biBitCount >> 3);
  274. image_.reset(new uint8_t[bmi_.bmiHeader.biSizeImage]);
  275. if(m_Pos==RenderPosition::LEFT||m_Pos== RenderPosition::RIGHT)
  276. _rotate.reset(new uint8_t[bmi_.bmiHeader.biSizeImage]);
  277. }
  278. void CThreadWindow::FrameCallback(void* user_data,
  279. const uint8_t* yptr, int32_t strideY,
  280. const uint8_t* uptr, int32_t strideU,
  281. const uint8_t* vptr, int32_t strideV,
  282. const int32_t stride, const int frame_width,
  283. const int frame_height)
  284. {
  285. auto ptr = static_cast<CThreadWindow*>(user_data);
  286. ptr->OnArgb32FrameReady(yptr, strideY, uptr,strideU,vptr,strideV,stride, frame_width, frame_height);
  287. }
  288. void CThreadWindow::StartRender(bool b)
  289. {
  290. start_ = b;
  291. }
  292. void CThreadWindow::OnPaint(HWND hWnd)
  293. {
  294. PAINTSTRUCT ps;
  295. HDC hdc = BeginPaint(hWnd, &ps);
  296. // TODO: Add any drawing code that uses hdc here...
  297. if (start_)
  298. {
  299. RECT rc;
  300. ::GetClientRect(hWnd, &rc);
  301. //const uint8_t* image =
  302. //AutoLock<VideoRenderer> local_lock(renderer);
  303. //const BITMAPINFO& bmi = renderer->bmi();
  304. // std::lock_guard < std::mutex> l(buffer_lock_);
  305. int height = abs(bmi_.bmiHeader.biHeight);
  306. int width = bmi_.bmiHeader.biWidth;
  307. HDC dc_mem = ::CreateCompatibleDC(ps.hdc);
  308. ::SetStretchBltMode(dc_mem, HALFTONE);
  309. HDC all_dc[] = { ps.hdc, dc_mem };
  310. for (size_t i = 0; i < _countof(all_dc); ++i) {
  311. SetMapMode(all_dc[i], MM_ISOTROPIC);
  312. SetWindowExtEx(all_dc[i], width, height, NULL);
  313. SetViewportExtEx(all_dc[i], rc.right, rc.bottom, NULL);
  314. }
  315. HBITMAP bmp_mem = ::CreateCompatibleBitmap(ps.hdc, rc.right, rc.bottom);
  316. HGDIOBJ bmp_old = ::SelectObject(dc_mem, bmp_mem);
  317. POINT logical_area = { rc.right, rc.bottom };
  318. DPtoLP(ps.hdc, &logical_area, 1);
  319. HBRUSH brush = ::CreateSolidBrush(RGB(0, 0, 0));
  320. RECT logical_rect = { 0, 0, logical_area.x, logical_area.y };
  321. ::FillRect(dc_mem, &logical_rect, brush);
  322. ::DeleteObject(brush);
  323. int x = (logical_area.x / 2) - (width / 2);
  324. int y = (logical_area.y / 2) - (height / 2);
  325. StretchDIBits(dc_mem, x, y, width, height, 0, 0, width, height, image_.get(),
  326. &bmi_, DIB_RGB_COLORS, SRCCOPY);
  327. BitBlt(ps.hdc, 0, 0, logical_area.x, logical_area.y, dc_mem, 0, 0,
  328. SRCCOPY);
  329. // Cleanup.
  330. ::SelectObject(dc_mem, bmp_old);
  331. ::DeleteObject(bmp_mem);
  332. ::DeleteDC(dc_mem);
  333. }
  334. EndPaint(hWnd, &ps);
  335. }
  336. 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)
  337. {
  338. {
  339. // int32_t*pixels = (int32_t*)data;
  340. //std::lock_guard < std::mutex> l(buffer_lock_);
  341. if (RenderPosition::LEFT == m_Pos)
  342. {
  343. SetSize(height,width);
  344. uint8_t* i420_image_rotated = _rotate.get();////(uint8_t*)malloc(width * height * 3 ) ;
  345. uint8_t* i420_image_rotated_y_ptr = i420_image_rotated;
  346. uint8_t* i420_image_rotated_u_ptr = i420_image_rotated_y_ptr + (height * width);
  347. uint8_t* i420_image_rotated_v_ptr = i420_image_rotated_u_ptr + (int)(height * width * 0.25);
  348. libyuv::I420Rotate(yptr, width, uptr, width>>1, vptr, width>>1, i420_image_rotated_y_ptr,
  349. height,
  350. i420_image_rotated_u_ptr,
  351. height >>1,
  352. i420_image_rotated_v_ptr,
  353. height >>1,
  354. width,
  355. height, libyuv::RotationMode::kRotate270);
  356. yptr = i420_image_rotated_y_ptr;
  357. strideY = height;
  358. uptr = i420_image_rotated_u_ptr;
  359. strideU = height >> 1;
  360. vptr = i420_image_rotated_v_ptr;
  361. strideV = height >> 1;
  362. libyuv::I420ToARGB(yptr, strideY, uptr, strideU, vptr, strideV, image_.get(), height*4, height, width );
  363. }
  364. else if (RenderPosition::RIGHT == m_Pos)
  365. {
  366. SetSize(height, width);
  367. uint8_t* i420_image_rotated = _rotate.get();
  368. uint8_t* i420_image_rotated_y_ptr = i420_image_rotated;
  369. uint8_t* i420_image_rotated_u_ptr = i420_image_rotated_y_ptr + (height * width);
  370. uint8_t* i420_image_rotated_v_ptr = i420_image_rotated_u_ptr + (int)(height * width * 0.25);
  371. libyuv::I420Rotate(yptr, width, uptr, width >> 1, vptr, width >> 1, i420_image_rotated_y_ptr,
  372. height,
  373. i420_image_rotated_u_ptr,
  374. height >> 1,
  375. i420_image_rotated_v_ptr,
  376. height >> 1,
  377. width,
  378. height, libyuv::RotationMode::kRotate90);
  379. yptr = i420_image_rotated_y_ptr;
  380. strideY = height;
  381. uptr = i420_image_rotated_u_ptr;
  382. strideU = height >> 1;
  383. vptr = i420_image_rotated_v_ptr;
  384. strideV = height >> 1;
  385. libyuv::I420ToARGB(yptr, strideY, uptr, strideU, vptr, strideV, image_.get(), height * 4, height, width);
  386. }
  387. else
  388. {
  389. SetSize(width,height);
  390. libyuv::I420ToARGB(yptr, strideY, uptr, strideU, vptr, strideV, image_.get(), stride, width, height);
  391. }
  392. }
  393. ::InvalidateRect(m_hWnd, NULL, FALSE);
  394. }
  395. void CThreadWindow::SetSize(int32_t width, int32_t height)
  396. {
  397. if (width == bmi_.bmiHeader.biWidth && height == -bmi_.bmiHeader.biHeight) {
  398. return;
  399. }
  400. // if (m_Pos == CameraPosition::CAR_LEFT || m_Pos == CameraPosition::CAR_RIGHT)
  401. // {
  402. // bmi_.bmiHeader.biWidth = height;
  403. // bmi_.bmiHeader.biHeight = -width;
  404. // }
  405. // else
  406. {
  407. bmi_.bmiHeader.biWidth = width;
  408. bmi_.bmiHeader.biHeight = -height;
  409. }
  410. bmi_.bmiHeader.biSizeImage =
  411. width * height * (bmi_.bmiHeader.biBitCount >> 3);
  412. image_.reset(new uint8_t[bmi_.bmiHeader.biSizeImage]);
  413. if (m_Pos == RenderPosition::LEFT || m_Pos == RenderPosition::RIGHT)
  414. _rotate.reset(new uint8_t[bmi_.bmiHeader.biSizeImage]);
  415. }
  416. void CThreadWindow::DelayNextVideoReq()
  417. {
  418. m_DelayThread = std::thread(&CThreadWindow::AskVideoReq, this);
  419. m_DelayThread.detach();
  420. }
  421. void CThreadWindow::DelayDataChannel()
  422. {
  423. m_DelayThread = std::thread(&CThreadWindow::AskDataChannel, this);
  424. m_DelayThread.detach();
  425. }
  426. void CThreadWindow::DelayControlStart()
  427. {
  428. m_DelayThread = std::thread(&CThreadWindow::AskControlStart, this);
  429. m_DelayThread.detach();
  430. }
  431. void CThreadWindow::AskVideoReq()
  432. {
  433. Sleep(500);
  434. m_Client->WriteVideoReq(m_Peer, m_Pos);
  435. }
  436. void CThreadWindow::AskDataChannel()
  437. {
  438. Sleep(500);
  439. //bDataChannelCreated = true;
  440. RemoNet::CCAskDataChannel Req;
  441. m_PeerConnection->SetDataReady();
  442. CIOBuffer Buffer;
  443. MessageHead Head;
  444. Head.Command = RemoNet::CC_ASKDATACHANNEL;
  445. Head.Length = Req.ByteSize();
  446. Head.Serialize(Buffer.Buffer);
  447. auto ptr = Buffer.Buffer + MessageHead::Size();
  448. Req.SerializeToArray(ptr, Head.Length);
  449. Buffer.Length = Head.Length + MessageHead::Size();
  450. SendData(&Buffer);
  451. }
  452. void CThreadWindow::AskControlStart()
  453. {
  454. Sleep(500);
  455. _control = ControlState::Process;
  456. }
  457. void CThreadWindow::SendData(CIOBuffer* pBuffer)
  458. {
  459. m_PeerConnection->SendData(pBuffer);
  460. }
  461. ControlState CThreadWindow::GetControlState()
  462. {
  463. return _control;
  464. }
  465. /*
  466. void CThreadWindow::Notify(int8_t* buffer, int32_t size)
  467. {
  468. }
  469. void CThreadWindow::SetCanSocket(SocketCan* can)
  470. {
  471. }
  472. */