用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 = ▭
}
// 拷贝材质到渲染器
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 = ▭
}
re = SDL_RenderCopy(m_SdlRender, m_SdlTexture, NULL, prect);
if (re)
{
return false;
}
SDL_RenderPresent(m_SdlRender);
return true;
}