当前位置:   article > 正文

DXGI抓屏优化扩展:GPU硬件编码保存文件即录像为MP4和FLV,外加麦克风+计算机声音_dxgi采集到的数据是在gpu中存储使用ffmpeg 的nvenc 进行视频编码

dxgi采集到的数据是在gpu中存储使用ffmpeg 的nvenc 进行视频编码

DXGI抓屏优化扩展:GPU硬件编码保存文件即录像为MP4和FLV,外加麦克风+计算机声音

我们一般要实现某个功能,首先希望能找到对应的DEMO,比如我们做屏幕共享,在WIN10下,首先想到的就是DXGI技术,帧率和效率是非常不错的,这里不讲性能,讲下怎么扩展某些功能:

前面一篇文章已经介绍和实现了以下功能:

  1. 鼠标功能:
  2. 数据获取
  3. 多显示器需求(多屏,副显,扩展屏说法很多)

写这篇文章的目的在于继续扩大其高性能应用,我们继续扩展以下功能:

  1. 硬件GPU编码
  2. 录像同时保存为MP4和FLV
  3. 录像时同时预览视频(D3D显示)
  4. 声音输入多种选择:麦克风,计算机声音,麦克风+计算机声音混合

先说第一个:

DXGI如此性能优秀的截屏方法,如果我们再用H264软件编码,是不是有点暴殄天物

(拼音是bào tiǎn tiān wù),既然可以用dxgi抓屏,也可以用显卡加速进行编码,目前代码支持INTEL的QSV硬件加速和英伟达的CUDA硬件加速编码,当然也可以选择H264软编码,前者和后者主要还是性能上的差异,经过硬件加速的H264编码比软件编码更快,缺点是兼容性不是很好,不过既然都支持DXGI了,肯定也有显卡编码加速的支持。

好的,我们加上吧,直接上代码就是这么简单粗暴:

  1. bool CFFFindEncoder::Find(char* szName)
  2. {
  3. //MessageBox(0,L"1",0,0);
  4. AVCodecContext *c= NULL;
  5. //AVFrame *frame;
  6. AVPacket *pkt;
  7. AVCodec *codec=avcodec_find_encoder_by_name(szName);
  8. if(codec==0)
  9. return false;
  10. //MessageBox(0,L"2",0,0);
  11. c = avcodec_alloc_context3(codec);
  12. if (!c)
  13. {
  14. return false;
  15. }
  16. //MessageBox(0,L"3",0,0);
  17. pkt = av_packet_alloc();
  18. if (!pkt)
  19. {
  20. return false;
  21. }
  22. c->bit_rate = 8000000;
  23. c->width = 1920;
  24. c->height = 1080;
  25. c->time_base.num=1;
  26. c->time_base.den=25;
  27. c->framerate.num=25;
  28. c->framerate.den=1;
  29. c->gop_size = 10;
  30. c->max_b_frames = 0;
  31. c->pix_fmt = AV_PIX_FMT_NV12;//AV_PIX_FMT_YUV420P;
  32. if (codec->id == AV_CODEC_ID_H264)
  33. av_opt_set(c->priv_data, "preset", "slow", 0);
  34. int ret = avcodec_open2(c, codec, NULL);
  35. if (ret < 0) {
  36. return false;
  37. }
  38. //MessageBox(0,L"4",0,0);
  39. avcodec_free_context(&c);
  40. av_packet_free(&pkt);
  41. return true;
  42. }

以上代码是判断是否支持硬件编码:

调用代码为:

 

  1. int bOK0=0;//enc.Find(L"opus");
  2. char* Encoder[4]={"h264_qsv","h264_nvenc","libx264","h264_amf"};
  3. for(int i=0;i<4;i++)
  4. {
  5. char* szEncoder=Encoder[i];
  6. bOK0=enc.Find(szEncoder);//hevc_nvenc h264_qsv
  7. if(bOK0)
  8. {
  9. m_nEncoder=i;
  10. PCHAR szA=Encoder[i];
  11. m_cx=(m_cx/16)*16;
  12. m_cy=(m_cy==768?768:m_cy);
  13. enc.Init(szA,m_cx ,m_cy);
  14. break;
  15. }
  16. }

如上面代码所示, h264_qsv显卡为intel GPU,h264_nvenc显卡为英伟达 GPU,libx264为软件编码,h264_amf还没测试,下次买个AMD的笔记本测试,不过代价挺大,哎,开发也不容易啊!

编码器初始化后就可以编码图像数据(YUV)为视频数据(H264)了,dxgi输出数据为RGB32,我们需要转换为NV12或者YV12,一般用libyuv进行转换效率更高。来吧,上代码:

  1. static int ARGBToYv12(uint8* src_frame,uint8* dst_frame,int width,int height)
  2. {
  3. uint8* yplane= dst_frame;
  4. uint8* uplane= dst_frame + width * height;
  5. uint8* vplane= uplane+ (width * height/4);
  6. int n = libyuv::ARGBToI420(src_frame,width*4,yplane, width,uplane, width/2,vplane, width/2, width, height);
  7. return n;
  8. }
  9. static int ARGBToNv12(uint8* src_frame,uint8* dst_frame,int width,int height)
  10. {
  11. uint8* yplane= dst_frame;
  12. uint8* uplane= dst_frame + width * height;
  13. uint8* vplane= uplane+ (width * height/4);
  14. int n = libyuv::ARGBToNV12(src_frame,width*4,yplane, width,uplane, width, width, height);
  15. return n;
  16. }

这个颜色空间转换速度很NICE,要做就做最好,这是我的原则! 

先写到这里,下次继续写。。。尽请期待!QQ35744025联系我,美女优先

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/430049
推荐阅读
相关标签
  

闽ICP备14008679号