#include "preheader.h" #include "CSdlProc.h" extern "C" { #include #include #include #include #include }; #include #pragma comment(lib, "SDL2_ttf.LIB") #pragma comment(lib, "SDL2_gfx.LIB") #pragma comment(lib, "sdl2main.lib") #pragma comment(lib, "sdl2.lib") bool CSdlProc::m_bUseDispalyArea = false; CSdlProc::CSdlProc() { //初始化字体库 TTF_Init(); m_sdlRect = new SDL_Rect; if (m_pFont == nullptr) { std::string fileName = std::string(QCoreApplication::applicationDirPath().toLocal8Bit()); fileName += "\\font\\msyh.ttc"; m_pFont = TTF_OpenFont(fileName.c_str(), 40); if (!m_pFont) { return; } } } CSdlProc::~CSdlProc() { if (m_pFont!=nullptr) { TTF_CloseFont(m_pFont); } if (m_sdlRect!=nullptr) { delete m_sdlRect; m_sdlRect = nullptr; } } bool CSdlProc::Init(void * pWnd, int nVideoWidth, int nVideoHeight, bool bHard) { if (m_pFrameYUV != nullptr) { av_frame_free(&m_pFrameYUV); } if (m_out_buffer != nullptr) { av_free(m_out_buffer); m_out_buffer = nullptr; } m_pFrameYUV = av_frame_alloc(); m_out_buffer = (uint8_t *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, nVideoWidth, nVideoHeight, 1)); av_image_fill_arrays(m_pFrameYUV->data, m_pFrameYUV->linesize, m_out_buffer, AV_PIX_FMT_YUV420P, nVideoWidth, nVideoHeight, 1); if (bHard) { m_img_convert_ctx = sws_getContext(nVideoWidth, nVideoHeight, /*AV_PIX_FMT_YUV420P*/AV_PIX_FMT_NV12, nVideoWidth, nVideoHeight, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); } else { m_img_convert_ctx = sws_getContext(nVideoWidth, nVideoHeight, AV_PIX_FMT_YUV420P, nVideoWidth, nVideoHeight, AV_PIX_FMT_YUV420P, /*SWS_BILINEAR*/SWS_BICUBIC, NULL, NULL, NULL); } //SDL 2.0 Support for multiple windows if (m_screen == nullptr) { /*m_screen = SDL_CreateWindow("VIDEO Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, nVideoWidth, nVideoHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);*/ m_screen = SDL_CreateWindowFrom(pWnd); if (m_screen==nullptr) { return false; } m_sdlRenderer = SDL_CreateRenderer(m_screen, -1, SDL_RENDERER_SOFTWARE| SDL_RENDERER_PRESENTVSYNC); m_sdlTexture = SDL_CreateTexture(m_sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, nVideoWidth, nVideoHeight); } else { SDL_RenderClear(m_sdlRenderer); SDL_DestroyTexture(m_sdlTexture); m_sdlTexture = nullptr; SDL_DestroyRenderer(m_sdlRenderer); m_sdlRenderer = nullptr; m_sdlRenderer = SDL_CreateRenderer(m_screen, -1, SDL_RENDERER_SOFTWARE | SDL_RENDERER_PRESENTVSYNC); m_sdlTexture = SDL_CreateTexture(m_sdlRenderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, nVideoWidth, nVideoHeight); } SDL_ShowWindow(m_screen); return true; } void CSdlProc::DisplayFrame(AVFrame *pFrame) { int nRet = 0; if (m_img_convert_ctx==nullptr) { return; } sws_scale(m_img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pFrame->height, m_pFrameYUV->data, m_pFrameYUV->linesize); nRet = SDL_UpdateTexture(m_sdlTexture, NULL, m_pFrameYUV->data[0], m_pFrameYUV->linesize[0]); //SDL_UpdateTexture(m_sdlTexture, NULL, pFrame->data[0], pFrame->linesize[0]); //SDL_UpdateYUVTexture(m_sdlTexture, &m_sdlRect, // m_pFrameYUV->data[0], m_pFrameYUV->linesize[0], // m_pFrameYUV->data[1], m_pFrameYUV->linesize[1], // m_pFrameYUV->data[2], m_pFrameYUV->linesize[2]); //OutputDebugPrintf("VideoPlayer SDL_UpdateTexture nRet %d %s", nRet, SDL_GetError()); nRet = SDL_RenderClear(m_sdlRenderer); nRet = SDL_RenderCopy(m_sdlRenderer, m_sdlTexture, NULL, m_sdlRect); if (m_bUseDispalyArea && m_bDisplayArea) { DisplayChooseArea(m_ptArea); } if (m_bDisplayRect) { DisplayChooseAreaRect(m_ptlt, m_ptbr); } SDL_RenderPresent(m_sdlRenderer); } void CSdlProc::DisplayFrame(uint8_t* pData, int nWidth, int nHeight) { int nRet = 0; if (m_img_convert_ctx == nullptr) { return; } //创建一个AVFrame类似的结构体 unsigned char** pFrameData = new unsigned char*[4]; pFrameData[0] = pData; pFrameData[1] = pFrameData[0] + nWidth * nHeight; pFrameData[2] = pFrameData[1] + nWidth * nHeight / 4; int* lineSizeArray = new int[3]; lineSizeArray[0] = nWidth; lineSizeArray[1] = nWidth >> 1; lineSizeArray[2] = nWidth >> 1; //nRet = sws_scale(m_img_convert_ctx, (const uint8_t* const*)pFrameData, lineSizeArray, 0, nWidth, // m_pFrameYUV->data, m_pFrameYUV->linesize); memcpy(m_pFrameYUV->data[0], pData/*pFrameData[0]*/, nWidth * nHeight); memcpy(m_pFrameYUV->data[1], pData + nWidth*nHeight /*pFrameData[1]*/, nWidth * nHeight / 4); memcpy(m_pFrameYUV->data[2], pData + nWidth * nHeight*5/4, nWidth * nHeight / 4); memcpy(m_pFrameYUV->linesize, lineSizeArray, sizeof(int) * 3); nRet = SDL_UpdateTexture(m_sdlTexture, NULL, m_pFrameYUV->data[0], m_pFrameYUV->linesize[0]); //SDL_UpdateTexture(m_sdlTexture, NULL, pFrame->data[0], pFrame->linesize[0]); //SDL_UpdateYUVTexture(m_sdlTexture, &m_sdlRect, // m_pFrameYUV->data[0], m_pFrameYUV->linesize[0], // m_pFrameYUV->data[1], m_pFrameYUV->linesize[1], // m_pFrameYUV->data[2], m_pFrameYUV->linesize[2]); //OutputDebugPrintf("VideoPlayer SDL_UpdateTexture nRet %d %s", nRet, SDL_GetError()); nRet = SDL_RenderClear(m_sdlRenderer); nRet = SDL_RenderCopy(m_sdlRenderer, m_sdlTexture, NULL, m_sdlRect); if (m_bUseDispalyArea && m_bDisplayArea) { DisplayChooseArea(m_ptArea); } if (m_bDisplayRect) { DisplayChooseAreaRect(m_ptlt, m_ptbr); } SDL_RenderPresent(m_sdlRenderer); } void CSdlProc::SetRect(int nOffset_x, int nOffset_y, int nWidth, int nHeight) { m_sdlRect->x = nOffset_x; m_sdlRect->y = nOffset_y; m_sdlRect->w = nWidth; m_sdlRect->h = nHeight; } void CSdlProc::Destroy() { if (m_pFrameYUV!=nullptr) { av_frame_free(&m_pFrameYUV); } if (m_out_buffer != nullptr) { av_free(m_out_buffer); m_out_buffer = nullptr; } SDL_RenderClear(m_sdlRenderer); SDL_DestroyTexture(m_sdlTexture); m_sdlTexture = nullptr; SDL_DestroyRenderer(m_sdlRenderer); m_sdlRenderer = nullptr; SDL_DestroyWindow(m_screen); m_screen = nullptr; } void CSdlProc::SetUseDispalyArea(bool bUseDispalyArea) { m_bUseDispalyArea = bUseDispalyArea; } void CSdlProc::DisplayReconn() { SDL_RenderClear(m_sdlRenderer); TTF_SetFontStyle(m_pFont, TTF_STYLE_NORMAL /*TTF_STYLE_ITALIC | TTF_STYLE_BOLD*/); //创建文本表面 SDL_Color color2 = { 255,255,255,255 }; SDL_Surface *pTextSurface = NULL;//文本表面 SDL_Texture *pTextTexture = NULL;//文本纹理 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) }; pTextSurface = TTF_RenderUTF8_Solid(m_pFont, u8"网络异常,请检查设备网络连接,设备重连中......", color2); //创建文本纹理 pTextTexture = SDL_CreateTextureFromSurface(m_sdlRenderer, pTextSurface); SDL_RenderCopy(m_sdlRenderer, pTextTexture, NULL, &sdlRectFont); SDL_FreeSurface(pTextSurface); //释放写有文字的surface SDL_DestroyTexture(pTextTexture); SDL_SetRenderDrawColor(m_sdlRenderer,70, 97, 146,128); SDL_RenderPresent(m_sdlRenderer); } void CSdlProc::DisplayChooseArea(const QPoint & pt) { const int nWidthIn = 80 / 2; const int nHieghtIn = 80 / 2; const int nWidthOut = m_sdlRect->w / 2; const int nHeightOut = m_sdlRect->h / 2; const int nLengthLine = 100 / 2; const int nWidthInner = 3; const int nWidthOuter = 3; //外圈4个角线 thickLineRGBA(m_sdlRenderer, pt.x() - nWidthOut / 2, pt.y() - nHeightOut / 2, pt.x() - nWidthOut / 2, pt.y() - nHeightOut / 2 + nLengthLine, 2, 255, 255, 255, 128); thickLineRGBA(m_sdlRenderer, pt.x() - nWidthOut / 2, pt.y() - nHeightOut / 2, pt.x() - nWidthOut / 2 + nLengthLine, pt.y() - nHeightOut / 2, 2, 255, 255, 255, 128); thickLineRGBA(m_sdlRenderer, pt.x() + nWidthOut / 2, pt.y() + nHeightOut / 2, pt.x() + nWidthOut / 2, pt.y() + nHeightOut / 2 - nLengthLine, 2, 255, 255, 255, 128); thickLineRGBA(m_sdlRenderer, pt.x() + nWidthOut / 2, pt.y() + nHeightOut / 2, pt.x() + nWidthOut / 2 - nLengthLine, pt.y() + nHeightOut / 2, 2, 255, 255, 255, 128); thickLineRGBA(m_sdlRenderer, pt.x() - nWidthOut / 2, pt.y() + nHeightOut / 2, pt.x() - nWidthOut / 2, pt.y() + nHeightOut / 2 - nLengthLine, 2, 255, 255, 255, 128); thickLineRGBA(m_sdlRenderer, pt.x() - nWidthOut / 2, pt.y() + nHeightOut / 2, pt.x() - nWidthOut / 2 + nLengthLine, pt.y() + nHeightOut / 2, 2, 255, 255, 255, 128); thickLineRGBA(m_sdlRenderer, pt.x() + nWidthOut / 2, pt.y() - nHeightOut / 2, pt.x() + nWidthOut / 2, pt.y() - nHeightOut / 2 + nLengthLine, 2, 255, 255, 255, 128); thickLineRGBA(m_sdlRenderer, pt.x() + nWidthOut / 2, pt.y() - nHeightOut / 2, pt.x() + nWidthOut / 2 - nLengthLine, pt.y() - nHeightOut / 2, 2, 255, 255, 255, 128); /*SDL_Rect rectIn = { pt.x() - nWidthIn / 2, pt.y() - nHieghtIn / 2, nWidthIn, nHieghtIn }; rectangleRGBA(m_sdlRenderer, pt.x() - nWidthIn / 2, pt.y() - nHieghtIn / 2, pt.x() + nWidthIn / 2, pt.y() + nHieghtIn / 2, 255, 255, 255, 255);*/ //打开字体 if (m_pFont != nullptr) { TTF_SetFontStyle(m_pFont, TTF_STYLE_ITALIC | TTF_STYLE_BOLD); //创建文本表面 SDL_Color color2 = { 255,255,255,128 }; SDL_Surface *pTextSurface = NULL;//文本表面 SDL_Texture *pTextTexture = NULL;//文本纹理 pTextSurface = TTF_RenderUTF8_Solid(m_pFont, m_strText.c_str(), color2); //创建文本纹理 pTextTexture = SDL_CreateTextureFromSurface(m_sdlRenderer, pTextSurface); SDL_Rect sdlRectFont = { pt.x() + nWidthOut / 4, pt.y() - 20, 60, TTF_FontHeight(m_pFont) }; SDL_RenderCopy(m_sdlRenderer, pTextTexture, NULL, &sdlRectFont); SDL_FreeSurface(pTextSurface); //释放写有文字的surface SDL_DestroyTexture(pTextTexture); //内圈矩形 thickLineRGBA(m_sdlRenderer, pt.x() - nWidthIn / 2, pt.y() - nHieghtIn / 2, pt.x() + nWidthIn / 2, pt.y() - nHieghtIn / 2, nWidthInner, 255, 255, 255, 128); thickLineRGBA(m_sdlRenderer, pt.x() + nWidthIn / 2, pt.y() - nHieghtIn / 2, pt.x() + nWidthIn / 2, pt.y() + nHieghtIn / 2, nWidthInner, 255, 255, 255, 128); thickLineRGBA(m_sdlRenderer, pt.x() + nWidthIn / 2, pt.y() + nHieghtIn / 2, pt.x() - nWidthIn / 2, pt.y() + nHieghtIn / 2, nWidthInner, 255, 255, 255, 128); thickLineRGBA(m_sdlRenderer, pt.x() - nWidthIn / 2, pt.y() + nHieghtIn / 2, pt.x() - nWidthIn / 2, pt.y() - nHieghtIn / 2, nWidthInner, 255, 255, 255, 128); } } void CSdlProc::DisplayChooseAreaRect(const QPoint & ptlt, const QPoint & ptbr) { thickLineRGBA(m_sdlRenderer, ptlt.x() , ptlt.y(), ptlt.x(), ptbr.y(), 3, 255, 255, 255, 128); thickLineRGBA(m_sdlRenderer, ptlt.x(), ptlt.y(), ptbr.x(), ptlt.y(), 3, 255, 255, 255, 128); thickLineRGBA(m_sdlRenderer, ptbr.x(), ptlt.y(), ptbr.x(), ptbr.y(), 3, 255, 255, 255, 128); thickLineRGBA(m_sdlRenderer, ptlt.x(), ptbr.y(), ptbr.x(), ptbr.y(), 3, 255, 255, 255, 128); }