SDL直接渲染yuv视频帧数据

打印 上一主题 下一主题

主题 703|帖子 703|积分 2109

用ffmpeg解码出来的视频数据都是yuv视频帧,直接用sdl渲染可以有效的降低系统的cpu资源
直接上代码把 
  1. SDLRender::SDLRender()
  2. {
  3.         SDL_Init(SDL_INIT_VIDEO);
  4.         m_spN12Chech = std::make_shared<std::vector<uint8_t>>();
  5. }
复制代码
  1. bool SDLRender::DrawFrame(AVFrame *frame)
  2. {
  3.         std::unique_lock<std::mutex> locker(m_mtDrawFrame);
  4.         if (!frame)
  5.         {
  6.                 return false;
  7.         }
  8.         if (!m_SdlRender)
  9.         {
  10.                 m_SdlRender = SDL_CreateRenderer(m_SdlWindow, -1, SDL_RendererFlags::SDL_RENDERER_ACCELERATED);
  11.         }
  12.         if (frame->width != m_tureWidth || frame->height != m_tureHeight || !m_SdlTexture)
  13.         {
  14.                 m_tureWidth = frame->width;
  15.                 m_tureHeight = frame->height;
  16.                 if (m_SdlTexture)
  17.                 {
  18.                         SDL_DestroyTexture(m_SdlTexture);
  19.                         m_SdlTexture = nullptr;
  20.                 }
  21.                
  22.                 m_SdlTexture = SDL_CreateTexture(m_SdlRender, GetSDLFormat((AVPixelFormat)frame->format), SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height);
  23.         }
  24.         int linesize = 0;
  25.         switch (frame->format)
  26.         {
  27.         case AV_PIX_FMT_YUVJ420P:
  28.         case AV_PIX_FMT_YUV420P:
  29.                 return Draw(frame->data[0], frame->linesize[0], frame->data[1], frame->linesize[1], frame->data[2], frame->linesize[2]);
  30.         case AV_PIX_FMT_NV12:
  31.                 if (m_spN12Chech)
  32.                 {
  33.                         m_spN12Chech->clear();
  34.                 }
  35.                 else
  36.                 {
  37.                         return false;
  38.                 }
  39.                 linesize = frame->width;
  40.                 if (frame->linesize[0] == frame->width)
  41.                 {
  42.                         // 拷贝所有Y分量
  43.                         m_spN12Chech->insert(m_spN12Chech->end(), frame->data[0], frame->data[0] + frame->linesize[0] * frame->height);
  44.                         // 拷贝所有的UV分量
  45.                         m_spN12Chech->insert(m_spN12Chech->end(), frame->data[1], frame->data[1] + frame->linesize[1] * frame->height/2);
  46.                 }
  47.                 return Draw(m_spN12Chech->data(), linesize);
  48.         case AV_PIX_FMT_RGBA:
  49.         case AV_PIX_FMT_BGRA:
  50.         case AV_PIX_FMT_ARGB:
  51.                 return Draw(frame->data[0], frame->linesize[0]);
  52.         default:
  53.                 break;
  54.         }
  55.         return false;
  56. }
复制代码
  1. bool SDLRender::Draw(const unsigned char* y, int y_pitch, const unsigned char* u, int u_pitch, const unsigned char* v, int v_pitch)
  2. {
  3.         if (!y || !u || !v)
  4.         {
  5.                 return false;
  6.         }
  7.         std::unique_lock<std::mutex> locker(m_mtSdl);
  8.         if (!m_SdlWindow || !m_SdlRender || !m_SdlTexture)
  9.         {
  10.                 return false;
  11.         }
  12.         // 复制内存到显存
  13.         auto re = SDL_UpdateYUVTexture(m_SdlTexture, NULL, y, y_pitch, u, u_pitch, v, v_pitch);
  14.         if (re)
  15.         {
  16.                 return false;
  17.         }
  18.         // 清理渲染器
  19.         SDL_RenderClear(m_SdlRender);
  20.         // 如果用户手动设置了缩放,就按照用户设置的大小显示
  21.         // 如果用户没有设置,就传递null, 采用默认的窗口大小
  22.         SDL_Rect* prect = nullptr;
  23.         if (m_nScaleWidth > 0 || m_nScaleHeight > 0)
  24.         {
  25.                 SDL_Rect rect;
  26.                 rect.x = 0;
  27.                 rect.y = 0;
  28.                 rect.w = m_nScaleWidth;
  29.                 rect.h = m_nScaleHeight;
  30.                 prect = &rect;
  31.         }
  32.         // 拷贝材质到渲染器
  33.         re = SDL_RenderCopy(m_SdlRender, m_SdlTexture, NULL, prect);
  34.         if (re)
  35.         {
  36.                 return false;
  37.         }
  38.         SDL_RenderPresent(m_SdlRender);
  39.         return true;
  40. }
复制代码
  1. bool SDLRender::Draw(const unsigned char* data, int linesize)
  2. {
  3.         if (!data)
  4.         {
  5.                 return false;
  6.         }
  7.         std::unique_lock<std::mutex> locker(m_mtSdl);
  8.         if (!m_SdlWindow || !m_SdlRender || !m_SdlTexture)
  9.         {
  10.                 return false;
  11.         }
  12.         if (linesize <= 0)
  13.         {
  14.                 return false;
  15.         }
  16.         // 复制内存到显存
  17.         auto re = SDL_UpdateTexture(m_SdlTexture, NULL, data, linesize);
  18.         if (re)
  19.         {
  20.                 return false;
  21.         }
  22.         // 清理渲染器
  23.         SDL_RenderClear(m_SdlRender);
  24.         // 如果用户手动设置了缩放,就按照用户设置的大小显示
  25.         // 如果用户没有设置,就传递null, 采用默认的窗口大小
  26.         SDL_Rect *prect = nullptr;
  27.         if (m_nScaleWidth > 0 || m_nScaleHeight > 0)
  28.         {
  29.                 SDL_Rect rect;
  30.                 rect.x = 0;
  31.                 rect.y = 0;
  32.                 rect.w = m_nScaleWidth;
  33.                 rect.h = m_nScaleHeight;
  34.                 prect = &rect;
  35.         }
  36.         re = SDL_RenderCopy(m_SdlRender, m_SdlTexture, NULL, prect);
  37.         if (re)
  38.         {
  39.                 return false;
  40.         }
  41.         SDL_RenderPresent(m_SdlRender);
  42.         return true;
  43. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

西河刘卡车医

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表