SDL直接渲染yuv视频帧数据

用ffmpeg解码出来的视频数据都是yuv视频帧,直接用sdl渲染可以有效的降低系统的cpu资源

直接上代码把

cpp 复制代码
SDLRender::SDLRender()
{
	SDL_Init(SDL_INIT_VIDEO);
	m_spN12Chech = std::make_shared<std::vector<uint8_t>>();
}
cpp 复制代码
bool SDLRender::DrawFrame(AVFrame *frame)
{
	std::unique_lock<std::mutex> locker(m_mtDrawFrame);
	if (!frame)
	{
		return false;
	}

	if (!m_SdlRender)
	{
		m_SdlRender = SDL_CreateRenderer(m_SdlWindow, -1, SDL_RendererFlags::SDL_RENDERER_ACCELERATED);
	}

	if (frame->width != m_tureWidth || frame->height != m_tureHeight || !m_SdlTexture)
	{
		m_tureWidth = frame->width;
		m_tureHeight = frame->height;

		if (m_SdlTexture)
		{
			SDL_DestroyTexture(m_SdlTexture);
			m_SdlTexture = nullptr;
		}
		
		m_SdlTexture = SDL_CreateTexture(m_SdlRender, GetSDLFormat((AVPixelFormat)frame->format), SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height);
	}

	int linesize = 0;
	switch (frame->format)
	{
	case AV_PIX_FMT_YUVJ420P:
	case AV_PIX_FMT_YUV420P:
		return Draw(frame->data[0], frame->linesize[0], frame->data[1], frame->linesize[1], frame->data[2], frame->linesize[2]);
	case AV_PIX_FMT_NV12:
		if (m_spN12Chech)
		{
			m_spN12Chech->clear();
		}
		else
		{
			return false;
		}
		linesize = frame->width;
		if (frame->linesize[0] == frame->width)
		{
			// 拷贝所有Y分量
			m_spN12Chech->insert(m_spN12Chech->end(), frame->data[0], frame->data[0] + frame->linesize[0] * frame->height);
			// 拷贝所有的UV分量
			m_spN12Chech->insert(m_spN12Chech->end(), frame->data[1], frame->data[1] + frame->linesize[1] * frame->height/2);
		}
		return Draw(m_spN12Chech->data(), linesize);
	case AV_PIX_FMT_RGBA:
	case AV_PIX_FMT_BGRA:
	case AV_PIX_FMT_ARGB:
		return Draw(frame->data[0], frame->linesize[0]);
	default:
		break;
	}

	return false;
}
cpp 复制代码
bool SDLRender::Draw(const unsigned char* y, int y_pitch, const unsigned char* u, int u_pitch, const unsigned char* v, int v_pitch)
{
	if (!y || !u || !v)
	{
		return false;
	}

	std::unique_lock<std::mutex> locker(m_mtSdl);
	if (!m_SdlWindow || !m_SdlRender || !m_SdlTexture)
	{
		return false;
	}

	// 复制内存到显存
	auto re = SDL_UpdateYUVTexture(m_SdlTexture, NULL, y, y_pitch, u, u_pitch, v, v_pitch);
	if (re)
	{
		return false;
	}

	// 清理渲染器
	SDL_RenderClear(m_SdlRender);

	// 如果用户手动设置了缩放,就按照用户设置的大小显示
	// 如果用户没有设置,就传递null, 采用默认的窗口大小
	SDL_Rect* prect = nullptr;
	if (m_nScaleWidth > 0 || m_nScaleHeight > 0)
	{
		SDL_Rect rect;
		rect.x = 0;
		rect.y = 0;
		rect.w = m_nScaleWidth;
		rect.h = m_nScaleHeight;
		prect = &rect;
	}

	// 拷贝材质到渲染器
	re = SDL_RenderCopy(m_SdlRender, m_SdlTexture, NULL, prect);
	if (re)
	{
		return false;
	}

	SDL_RenderPresent(m_SdlRender);
	return true;
}
cpp 复制代码
bool SDLRender::Draw(const unsigned char* data, int linesize)
{
	if (!data)
	{
		return false;
	}

	std::unique_lock<std::mutex> locker(m_mtSdl);
	if (!m_SdlWindow || !m_SdlRender || !m_SdlTexture)
	{
		return false;
	}

	if (linesize <= 0)
	{
		return false;
	}

	// 复制内存到显存
	auto re = SDL_UpdateTexture(m_SdlTexture, NULL, data, linesize);
	if (re)
	{
		return false;
	}

	// 清理渲染器
	SDL_RenderClear(m_SdlRender);

	// 如果用户手动设置了缩放,就按照用户设置的大小显示
	// 如果用户没有设置,就传递null, 采用默认的窗口大小
	SDL_Rect *prect = nullptr;
	if (m_nScaleWidth > 0 || m_nScaleHeight > 0)
	{
		SDL_Rect rect;
		rect.x = 0;
		rect.y = 0;
		rect.w = m_nScaleWidth;
		rect.h = m_nScaleHeight;
		prect = &rect;
	}
	re = SDL_RenderCopy(m_SdlRender, m_SdlTexture, NULL, prect);
	if (re)
	{
		return false;
	}

	SDL_RenderPresent(m_SdlRender);
	return true;
}
相关推荐
MediaTea18 分钟前
Pr 视频过渡:沉浸式视频 - VR 色度泄漏
音视频·vr
LNTON羚通30 分钟前
算法定制LiteAIServer摄像机实时接入分析平台烟火检测算法的主要功能
音视频·视频监控
EasyCVR6 小时前
EHOME视频平台EasyCVR视频融合平台使用OBS进行RTMP推流,WebRTC播放出现抖动、卡顿如何解决?
人工智能·算法·ffmpeg·音视频·webrtc·监控视频接入
简鹿办公7 小时前
使用 FFmpeg 进行音视频转换的相关命令行参数解释
ffmpeg·简鹿视频格式转换器·ffmpeg视频转换
冷凝女子8 小时前
【QT】海康视频及openCv抓拍正脸接口
qt·opencv·音视频·海康
安步当歌9 小时前
【WebRTC】视频编码链路中各个类的简单分析——VideoStreamEncoder
音视频·webrtc·视频编解码·video-codec
顾北川_野9 小时前
Android CALL关于电话音频和紧急电话设置和获取
android·音视频
顶呱呱程序9 小时前
2-143 基于matlab-GUI的脉冲响应不变法实现音频滤波功能
算法·matlab·音视频·matlab-gui·音频滤波·脉冲响应不变法
EasyCVR10 小时前
萤石设备视频接入平台EasyCVR多品牌摄像机视频平台海康ehome平台(ISUP)接入EasyCVR不在线如何排查?
运维·服务器·网络·人工智能·ffmpeg·音视频
runing_an_min10 小时前
ffmpeg 视频滤镜:屏蔽边框杂色- fillborders
ffmpeg·音视频·fillborders