CSdlProc.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. #include "preheader.h"
  2. #include "CSdlProc.h"
  3. extern "C"
  4. {
  5. #include <libswscale/swscale.h>
  6. #include <libavutil/imgutils.h>
  7. #include <libswresample/swresample.h>
  8. #include <sdl/SDL_ttf.h>
  9. #include <sdl/SDL.h>
  10. };
  11. #include <sdl/SDL2_gfxPrimitives.h>
  12. #pragma comment(lib, "SDL2_ttf.LIB")
  13. #pragma comment(lib, "SDL2_gfx.LIB")
  14. #pragma comment(lib, "sdl2main.lib")
  15. #pragma comment(lib, "sdl2.lib")
  16. bool CSdlProc::m_bUseDispalyArea = false;
  17. CSdlProc::CSdlProc()
  18. {
  19. //初始化字体库
  20. TTF_Init();
  21. m_sdlRect = new SDL_Rect;
  22. if (m_pFont == nullptr)
  23. {
  24. std::string fileName = std::string(QCoreApplication::applicationDirPath().toLocal8Bit());
  25. fileName += "\\font\\msyh.ttc";
  26. m_pFont = TTF_OpenFont(fileName.c_str(), 40);
  27. if (!m_pFont)
  28. {
  29. return;
  30. }
  31. }
  32. }
  33. CSdlProc::~CSdlProc()
  34. {
  35. if (m_pFont!=nullptr)
  36. {
  37. TTF_CloseFont(m_pFont);
  38. }
  39. if (m_sdlRect!=nullptr)
  40. {
  41. delete m_sdlRect;
  42. m_sdlRect = nullptr;
  43. }
  44. }
  45. bool CSdlProc::Init(void * pWnd, int nVideoWidth, int nVideoHeight, bool bHard)
  46. {
  47. if (m_pFrameYUV != nullptr)
  48. {
  49. av_frame_free(&m_pFrameYUV);
  50. }
  51. if (m_out_buffer != nullptr)
  52. {
  53. av_free(m_out_buffer);
  54. m_out_buffer = nullptr;
  55. }
  56. m_pFrameYUV = av_frame_alloc();
  57. m_out_buffer = (uint8_t *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, nVideoWidth, nVideoHeight, 1));
  58. av_image_fill_arrays(m_pFrameYUV->data, m_pFrameYUV->linesize, m_out_buffer, AV_PIX_FMT_YUV420P, nVideoWidth, nVideoHeight, 1);
  59. if (bHard)
  60. {
  61. m_img_convert_ctx = sws_getContext(nVideoWidth, nVideoHeight, /*AV_PIX_FMT_YUV420P*/AV_PIX_FMT_NV12,
  62. nVideoWidth, nVideoHeight, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
  63. }
  64. else
  65. {
  66. m_img_convert_ctx = sws_getContext(nVideoWidth, nVideoHeight, AV_PIX_FMT_YUV420P,
  67. nVideoWidth, nVideoHeight, AV_PIX_FMT_YUV420P, /*SWS_BILINEAR*/SWS_BICUBIC, NULL, NULL, NULL);
  68. }
  69. //SDL 2.0 Support for multiple windows
  70. if (m_screen == nullptr)
  71. {
  72. /*m_screen = SDL_CreateWindow("VIDEO Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
  73. nVideoWidth, nVideoHeight,
  74. SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);*/
  75. m_screen = SDL_CreateWindowFrom(pWnd);
  76. if (m_screen==nullptr)
  77. {
  78. return false;
  79. }
  80. m_sdlRenderer = SDL_CreateRenderer(m_screen, -1, SDL_RENDERER_SOFTWARE| SDL_RENDERER_PRESENTVSYNC);
  81. m_sdlTexture = SDL_CreateTexture(m_sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, nVideoWidth, nVideoHeight);
  82. }
  83. else
  84. {
  85. SDL_RenderClear(m_sdlRenderer);
  86. SDL_DestroyTexture(m_sdlTexture);
  87. m_sdlTexture = nullptr;
  88. SDL_DestroyRenderer(m_sdlRenderer);
  89. m_sdlRenderer = nullptr;
  90. m_sdlRenderer = SDL_CreateRenderer(m_screen, -1, SDL_RENDERER_SOFTWARE | SDL_RENDERER_PRESENTVSYNC);
  91. m_sdlTexture = SDL_CreateTexture(m_sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, nVideoWidth, nVideoHeight);
  92. }
  93. SDL_ShowWindow(m_screen);
  94. return true;
  95. }
  96. void CSdlProc::DisplayFrame(AVFrame *pFrame)
  97. {
  98. int nRet = 0;
  99. if (m_img_convert_ctx==nullptr)
  100. {
  101. return;
  102. }
  103. sws_scale(m_img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pFrame->height,
  104. m_pFrameYUV->data, m_pFrameYUV->linesize);
  105. nRet = SDL_UpdateTexture(m_sdlTexture, NULL, m_pFrameYUV->data[0], m_pFrameYUV->linesize[0]);
  106. //SDL_UpdateTexture(m_sdlTexture, NULL, pFrame->data[0], pFrame->linesize[0]);
  107. //SDL_UpdateYUVTexture(m_sdlTexture, &m_sdlRect,
  108. // m_pFrameYUV->data[0], m_pFrameYUV->linesize[0],
  109. // m_pFrameYUV->data[1], m_pFrameYUV->linesize[1],
  110. // m_pFrameYUV->data[2], m_pFrameYUV->linesize[2]);
  111. //OutputDebugPrintf("VideoPlayer SDL_UpdateTexture nRet %d %s", nRet, SDL_GetError());
  112. nRet = SDL_RenderClear(m_sdlRenderer);
  113. nRet = SDL_RenderCopy(m_sdlRenderer, m_sdlTexture, NULL, m_sdlRect);
  114. if (m_bUseDispalyArea && m_bDisplayArea)
  115. {
  116. DisplayChooseArea(m_ptArea);
  117. }
  118. if (m_bDisplayRect)
  119. {
  120. DisplayChooseAreaRect(m_ptlt, m_ptbr);
  121. }
  122. SDL_RenderPresent(m_sdlRenderer);
  123. }
  124. void CSdlProc::DisplayFrame(uint8_t* pData, int nWidth, int nHeight)
  125. {
  126. int nRet = 0;
  127. if (m_img_convert_ctx == nullptr)
  128. {
  129. return;
  130. }
  131. //创建一个AVFrame类似的结构体
  132. unsigned char** pFrameData = new unsigned char*[4];
  133. pFrameData[0] = pData;
  134. pFrameData[1] = pFrameData[0] + nWidth * nHeight;
  135. pFrameData[2] = pFrameData[1] + nWidth * nHeight / 4;
  136. int* lineSizeArray = new int[3];
  137. lineSizeArray[0] = nWidth;
  138. lineSizeArray[1] = nWidth >> 1;
  139. lineSizeArray[2] = nWidth >> 1;
  140. //nRet = sws_scale(m_img_convert_ctx, (const uint8_t* const*)pFrameData, lineSizeArray, 0, nWidth,
  141. // m_pFrameYUV->data, m_pFrameYUV->linesize);
  142. memcpy(m_pFrameYUV->data[0], pData/*pFrameData[0]*/, nWidth * nHeight);
  143. memcpy(m_pFrameYUV->data[1], pData + nWidth*nHeight /*pFrameData[1]*/, nWidth * nHeight / 4);
  144. memcpy(m_pFrameYUV->data[2], pData + nWidth * nHeight*5/4, nWidth * nHeight / 4);
  145. memcpy(m_pFrameYUV->linesize, lineSizeArray, sizeof(int) * 3);
  146. nRet = SDL_UpdateTexture(m_sdlTexture, NULL, m_pFrameYUV->data[0], m_pFrameYUV->linesize[0]);
  147. //SDL_UpdateTexture(m_sdlTexture, NULL, pFrame->data[0], pFrame->linesize[0]);
  148. //SDL_UpdateYUVTexture(m_sdlTexture, &m_sdlRect,
  149. // m_pFrameYUV->data[0], m_pFrameYUV->linesize[0],
  150. // m_pFrameYUV->data[1], m_pFrameYUV->linesize[1],
  151. // m_pFrameYUV->data[2], m_pFrameYUV->linesize[2]);
  152. //OutputDebugPrintf("VideoPlayer SDL_UpdateTexture nRet %d %s", nRet, SDL_GetError());
  153. nRet = SDL_RenderClear(m_sdlRenderer);
  154. nRet = SDL_RenderCopy(m_sdlRenderer, m_sdlTexture, NULL, m_sdlRect);
  155. if (m_bUseDispalyArea && m_bDisplayArea)
  156. {
  157. DisplayChooseArea(m_ptArea);
  158. }
  159. if (m_bDisplayRect)
  160. {
  161. DisplayChooseAreaRect(m_ptlt, m_ptbr);
  162. }
  163. SDL_RenderPresent(m_sdlRenderer);
  164. }
  165. void CSdlProc::SetRect(int nOffset_x, int nOffset_y, int nWidth, int nHeight)
  166. {
  167. m_sdlRect->x = nOffset_x;
  168. m_sdlRect->y = nOffset_y;
  169. m_sdlRect->w = nWidth;
  170. m_sdlRect->h = nHeight;
  171. }
  172. void CSdlProc::Destroy()
  173. {
  174. if (m_pFrameYUV!=nullptr)
  175. {
  176. av_frame_free(&m_pFrameYUV);
  177. }
  178. if (m_out_buffer != nullptr)
  179. {
  180. av_free(m_out_buffer);
  181. m_out_buffer = nullptr;
  182. }
  183. SDL_RenderClear(m_sdlRenderer);
  184. SDL_DestroyTexture(m_sdlTexture);
  185. m_sdlTexture = nullptr;
  186. SDL_DestroyRenderer(m_sdlRenderer);
  187. m_sdlRenderer = nullptr;
  188. SDL_DestroyWindow(m_screen);
  189. m_screen = nullptr;
  190. }
  191. void CSdlProc::SetUseDispalyArea(bool bUseDispalyArea)
  192. {
  193. m_bUseDispalyArea = bUseDispalyArea;
  194. }
  195. void CSdlProc::DisplayReconn()
  196. {
  197. SDL_RenderClear(m_sdlRenderer);
  198. TTF_SetFontStyle(m_pFont, TTF_STYLE_NORMAL /*TTF_STYLE_ITALIC | TTF_STYLE_BOLD*/);
  199. //创建文本表面
  200. SDL_Color color2 = { 255,255,255,255 };
  201. SDL_Surface *pTextSurface = NULL;//文本表面
  202. SDL_Texture *pTextTexture = NULL;//文本纹理
  203. SDL_Rect sdlRectFont = { m_sdlRect->w / 2 - 200, m_sdlRect->h / 2 - TTF_FontHeight(m_pFont) / 2, 400/*m_sdlRect->w*/, TTF_FontHeight(m_pFont) };
  204. pTextSurface = TTF_RenderUTF8_Solid(m_pFont, u8"网络异常,请检查设备网络连接,设备重连中......", color2);
  205. //创建文本纹理
  206. pTextTexture = SDL_CreateTextureFromSurface(m_sdlRenderer, pTextSurface);
  207. SDL_RenderCopy(m_sdlRenderer, pTextTexture, NULL, &sdlRectFont);
  208. SDL_FreeSurface(pTextSurface); //释放写有文字的surface
  209. SDL_DestroyTexture(pTextTexture);
  210. SDL_SetRenderDrawColor(m_sdlRenderer,70, 97, 146,128);
  211. SDL_RenderPresent(m_sdlRenderer);
  212. }
  213. void CSdlProc::DisplayChooseArea(const QPoint & pt)
  214. {
  215. const int nWidthIn = 80 / 2;
  216. const int nHieghtIn = 80 / 2;
  217. const int nWidthOut = m_sdlRect->w / 2;
  218. const int nHeightOut = m_sdlRect->h / 2;
  219. const int nLengthLine = 100 / 2;
  220. const int nWidthInner = 3;
  221. const int nWidthOuter = 3;
  222. //外圈4个角线
  223. thickLineRGBA(m_sdlRenderer, pt.x() - nWidthOut / 2, pt.y() - nHeightOut / 2,
  224. pt.x() - nWidthOut / 2, pt.y() - nHeightOut / 2 + nLengthLine, 2, 255, 255, 255, 128);
  225. thickLineRGBA(m_sdlRenderer, pt.x() - nWidthOut / 2, pt.y() - nHeightOut / 2,
  226. pt.x() - nWidthOut / 2 + nLengthLine, pt.y() - nHeightOut / 2, 2, 255, 255, 255, 128);
  227. thickLineRGBA(m_sdlRenderer, pt.x() + nWidthOut / 2, pt.y() + nHeightOut / 2,
  228. pt.x() + nWidthOut / 2, pt.y() + nHeightOut / 2 - nLengthLine, 2, 255, 255, 255, 128);
  229. thickLineRGBA(m_sdlRenderer, pt.x() + nWidthOut / 2, pt.y() + nHeightOut / 2,
  230. pt.x() + nWidthOut / 2 - nLengthLine, pt.y() + nHeightOut / 2, 2, 255, 255, 255, 128);
  231. thickLineRGBA(m_sdlRenderer, pt.x() - nWidthOut / 2, pt.y() + nHeightOut / 2,
  232. pt.x() - nWidthOut / 2, pt.y() + nHeightOut / 2 - nLengthLine, 2, 255, 255, 255, 128);
  233. thickLineRGBA(m_sdlRenderer, pt.x() - nWidthOut / 2, pt.y() + nHeightOut / 2,
  234. pt.x() - nWidthOut / 2 + nLengthLine, pt.y() + nHeightOut / 2, 2, 255, 255, 255, 128);
  235. thickLineRGBA(m_sdlRenderer, pt.x() + nWidthOut / 2, pt.y() - nHeightOut / 2,
  236. pt.x() + nWidthOut / 2, pt.y() - nHeightOut / 2 + nLengthLine, 2, 255, 255, 255, 128);
  237. thickLineRGBA(m_sdlRenderer, pt.x() + nWidthOut / 2, pt.y() - nHeightOut / 2,
  238. pt.x() + nWidthOut / 2 - nLengthLine, pt.y() - nHeightOut / 2, 2, 255, 255, 255, 128);
  239. /*SDL_Rect rectIn = { pt.x() - nWidthIn / 2, pt.y() - nHieghtIn / 2, nWidthIn, nHieghtIn };
  240. rectangleRGBA(m_sdlRenderer, pt.x() - nWidthIn / 2, pt.y() - nHieghtIn / 2, pt.x() + nWidthIn / 2, pt.y() + nHieghtIn / 2, 255, 255, 255, 255);*/
  241. //打开字体
  242. if (m_pFont != nullptr)
  243. {
  244. TTF_SetFontStyle(m_pFont, TTF_STYLE_ITALIC | TTF_STYLE_BOLD);
  245. //创建文本表面
  246. SDL_Color color2 = { 255,255,255,128 };
  247. SDL_Surface *pTextSurface = NULL;//文本表面
  248. SDL_Texture *pTextTexture = NULL;//文本纹理
  249. pTextSurface = TTF_RenderUTF8_Solid(m_pFont, m_strText.c_str(), color2);
  250. //创建文本纹理
  251. pTextTexture = SDL_CreateTextureFromSurface(m_sdlRenderer, pTextSurface);
  252. SDL_Rect sdlRectFont = { pt.x() + nWidthOut / 4, pt.y() - 20, 60, TTF_FontHeight(m_pFont) };
  253. SDL_RenderCopy(m_sdlRenderer, pTextTexture, NULL, &sdlRectFont);
  254. SDL_FreeSurface(pTextSurface); //释放写有文字的surface
  255. SDL_DestroyTexture(pTextTexture);
  256. //内圈矩形
  257. thickLineRGBA(m_sdlRenderer, pt.x() - nWidthIn / 2, pt.y() - nHieghtIn / 2,
  258. pt.x() + nWidthIn / 2, pt.y() - nHieghtIn / 2, nWidthInner, 255, 255, 255, 128);
  259. thickLineRGBA(m_sdlRenderer, pt.x() + nWidthIn / 2, pt.y() - nHieghtIn / 2,
  260. pt.x() + nWidthIn / 2, pt.y() + nHieghtIn / 2, nWidthInner, 255, 255, 255, 128);
  261. thickLineRGBA(m_sdlRenderer, pt.x() + nWidthIn / 2, pt.y() + nHieghtIn / 2,
  262. pt.x() - nWidthIn / 2, pt.y() + nHieghtIn / 2, nWidthInner, 255, 255, 255, 128);
  263. thickLineRGBA(m_sdlRenderer, pt.x() - nWidthIn / 2, pt.y() + nHieghtIn / 2,
  264. pt.x() - nWidthIn / 2, pt.y() - nHieghtIn / 2, nWidthInner, 255, 255, 255, 128);
  265. }
  266. }
  267. void CSdlProc::DisplayChooseAreaRect(const QPoint & ptlt, const QPoint & ptbr)
  268. {
  269. thickLineRGBA(m_sdlRenderer, ptlt.x() , ptlt.y(), ptlt.x(), ptbr.y(), 3, 255, 255, 255, 128);
  270. thickLineRGBA(m_sdlRenderer, ptlt.x(), ptlt.y(), ptbr.x(), ptlt.y(), 3, 255, 255, 255, 128);
  271. thickLineRGBA(m_sdlRenderer, ptbr.x(), ptlt.y(), ptbr.x(), ptbr.y(), 3, 255, 255, 255, 128);
  272. thickLineRGBA(m_sdlRenderer, ptlt.x(), ptbr.y(), ptbr.x(), ptbr.y(), 3, 255, 255, 255, 128);
  273. }