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;
}
相关推荐
薛定猫AI2 小时前
【深度解析】Gemini Omni 多模态生成与 Agent 化创作工作流:从视频编辑到 UI 生成的技术演进
人工智能·ui·音视频
四方云4 小时前
电销系统中FreeSWITCH桥接播放自定义振铃:被叫接听后振铃持续问题解决
ffmpeg
音视频牛哥10 小时前
大牛直播SDK(SmartMediaKit)Windows平台RTSP/RTMP直播播放SDK集成说明(C++版)
windows·音视频·实时音视频·windows rtsp播放器·windows rtmp播放器·超低延迟rtsp播放器·超低延迟rtmp播放器
EasyGBS12 小时前
1分钟讲清楚选EasyNVR还是国标GB28181视频平台EasyGBS:路线不同,别选错
音视频
日光明媚13 小时前
深度解析 SGLang 框架 Wan2.1 视频生成加速技术:从 49 分钟到 1 分钟的极致优化
人工智能·计算机视觉·aigc·音视频·sglang
小猿君13 小时前
谷歌I/O前夜Veo 4遭泄露,AI视频底层逻辑浮出水面
人工智能·音视频
南山有乔木78913 小时前
音频怎么转换MP3格式?M4A、WAV、FLAC转mp3实测有效的格式转换方法
音视频
不昀13 小时前
音频变压器Bourns SM-LP-5001国产替代选型指南
网络·音视频·以太网·网络通信·电子元器件
REDcker13 小时前
RGB与YUV像素格式详解
音视频·实时音视频·视频编解码·yuv·rgb
水上冰石13 小时前
v1-5-pruned-emaonly.safetensors 搭配mm_sd_v15_v2.ckpt 生成视频,具体操作步骤
stable diffusion·音视频·文生视频