用ffmpeg解码出来的视频数据都是yuv视频帧,直接用sdl渲染可以有效的降低系统的cpu资源
直接上代码把
SDLRender::SDLRender()
{SDL_Init(SDL_INIT_VIDEO);m_spN12Chech = std::make_shared<std::vector<uint8_t>>();
}
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;
}
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;
}
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;
}