| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 | 
#include "preheader.h"#include "CSdlProc.h"extern "C"{#include <libswscale/swscale.h>#include <libavutil/imgutils.h>#include <libswresample/swresample.h>#include <sdl/SDL_ttf.h>#include <sdl/SDL.h>};#include <sdl/SDL2_gfxPrimitives.h>#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);}
 |