MFC利用SDL 绘制FFMPEG AVFrame 绘制YUV420P

本文介绍了一个使用SDL库进行音视频绘制的类SDLDraw,该类通过与FFmpeg结合,实现了音视频帧的显示功能。文章详细展示了如何创建窗口、初始化渲染器、更新纹理以及清除画布等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码比较简单

class SDLDraw{  
private:
	SDL_Window * pWindow;
	SDL_Rect m_DrawRect;
	SDL_Renderer * pRender;
	SDL_Texture * pTexture; 
	HWND m_hWnd;
	int m_Width;
	int m_Height;
public: 
	SDLDraw();
	~SDLDraw();
	void Init(HWND hWnd);
	void Destory();
	void Draw(AVFrame* frame);
	void Clear();

};

	#define Y_BLACK	0
	#define U_BLACK	128
	#define V_BLACK	128 
	#pragma comment(lib, "SDL2.lib")
	SDLDraw::SDLDraw(){
		SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO);
		pWindow=NULL;
		pRender=NULL;
		pTexture=NULL;
	}
	SDLDraw::~SDLDraw(){
		Destory();
	}
	void SDLDraw::Init(HWND hWnd){
		LONG_PTR WinMessage= (LONG_PTR)GetWindowLongPtr(hWnd, GWLP_WNDPROC);
		pWindow = SDL_CreateWindowFrom(hWnd ); 
		SetWindowLongPtr(hWnd, GWLP_WNDPROC,  WinMessage);
		m_DrawRect.x=0;
	m_DrawRect.y=0;
	int iWidth = 0;
	int iHeight = 0; 
	SDL_GetWindowSize( pWindow, &iWidth, &iHeight );
	m_DrawRect.w=iWidth;
	m_DrawRect.h=iHeight;
	pRender = SDL_CreateRenderer( pWindow,-1, SDL_RENDERER_TARGETTEXTURE ); 
	m_Width=176;
	m_Height=144;
	m_hWnd=hWnd;
}
void SDLDraw::Destory(){
	if ( pTexture != NULL )
	{
		SDL_DestroyTexture( pTexture );
		pTexture = NULL    ;
	}

	if ( pRender != NULL )
	{
		SDL_DestroyRenderer( pRender );
		pRender = NULL;
	} 
	if ( NULL != pWindow )
	{
		SDL_DestroyWindow( pWindow );
		pWindow = NULL;
	}
}
void SDLDraw::Draw(AVFrame* frame){
	if(!pWindow) return;
	if(!frame) return;
	int nWidth=frame->width;
	int nHeight=frame->height;
	if(nWidth!=m_Width||nHeight!=m_Height){
		if ( pTexture != NULL )
		{
			SDL_DestroyTexture( pTexture );
			pTexture = NULL    ;
		}
	}
	m_Width=nWidth;
	m_Height=nHeight;
	if(!pTexture){ 
		pTexture = SDL_CreateTexture( pRender,SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, nWidth, nHeight );  
	} 
	int iPitch = m_Width*SDL_BYTESPERPIXEL(SDL_PIXELFORMAT_YV12); 
	VideoConvter convert((AVPixelFormat)frame->format,PIX_FMT_YUV420P,nWidth,nHeight,nWidth,nHeight); 
	if(convert.Convert(frame)>=0){   
		const AVFrame* cframe=convert.GetFrame(); 
		SDL_UpdateTexture( pTexture,NULL, cframe->data[0], iPitch );
	}
	SDL_RenderClear( pRender );
	SDL_Rect sdlRT;
	sdlRT.x = 0;
	sdlRT.y = 0; 
	sdlRT.h = nHeight;
	sdlRT.w = nWidth;
	SDL_RenderCopy( pRender, pTexture, &sdlRT, &m_DrawRect );
	SDL_RenderPresent( pRender );  
}  


void SDLDraw::Clear(){  
	int size=avpicture_get_size ((AVPixelFormat) PIX_FMT_YUV420P, m_DrawRect.w,m_DrawRect.h);
	uint8_t* yuvBuffer=(uint8_t*) av_malloc(size);
	AVFrame* pFrame = av_frame_alloc(); 
	if (pFrame&&avpicture_fill((AVPicture*) pFrame, yuvBuffer, PIX_FMT_YUV420P, m_DrawRect.w,m_DrawRect.h)>= 0) {
		pFrame->width =  m_DrawRect.w;
		pFrame->height = m_DrawRect.h;
		pFrame->format = PIX_FMT_YUV420P;  
		memset(pFrame->data[0],Y_BLACK,pFrame->linesize[0]* m_DrawRect.h);
		memset(pFrame->data[1],U_BLACK,pFrame->linesize[1]* (m_DrawRect.h>>1));
		memset(pFrame->data[2],V_BLACK,pFrame->linesize[2]* (m_DrawRect.h>>1));
	}
	Draw(pFrame);
	if(pFrame){
		av_frame_free(&pFrame);
	}
	av_free(yuvBuffer);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值