webrtc-m79-msvc编译H264

0 写在前面

本文主要参考:webrtc 4577版本vs编译_tusong86的博客-CSDN博客

4577也就是m93,由于源码版本的不同,可能存在一定的出入,可根据实际情况进行修改;

感谢作者的付出;

1 编译参数

powershell运行:

// debug 需要编译参数 enable_iterator_debugging=true

gn gen h264-debug-m79 --args='is_debug=true use_lld=false is_clang=false treat_warnings_as_errors=false use_custom_libcxx=false is_component_build=false use_rtti=true rtc_enable_protobuf=false rtc_build_examples=true enable_iterator_debugging=true rtc_use_h264=true use_openh264=true ffmpeg_branding=\"Chrome\" proprietary_codecs=true' --ide=vs2019

查看参数是否生效:

gn args h264-debug-m79 --list=rtc_use_h264

gn args h264-debug-m79 --list=use_openh264

//release 不需要编译参数 enable_iterator_debugging=true

gn gen h264-release-m79 --args='is_debug=false use_lld=false is_clang=false treat_warnings_as_errors=false use_custom_libcxx=false is_component_build=false use_rtti=true rtc_enable_protobuf=false rtc_build_examples=true rtc_use_h264=true use_openh264=true ffmpeg_branding=\"Chrome\" proprietary_codecs=true' --ide=vs2019

查看参数是否生效:

gn args h264-release-m79 --list=rtc_use_h264

gn args h264-release-m79 --list=use_openh264

为了避免下面2.3小节的问题,需要将webrtc的编译参数修改为MD(d),具体修改如下所示:

2 编译错误以及修复

2.1 错误一

解决方案:

注释掉代码:

See: bugs.webrtc.org/9213#c13

具体修改如下图:

2.2 错误二

解决方案:

注释掉\third_party\ffmpeg\libavcodec\pcm.c的最后一行,具体如下图:

2.3 错误三

2.3.1 问题描述

解决此问题需要使用自己MSVC编译的x64 ffmpeg动态库,如何编译ffmpeg的动态库可以采用参考链接[2],自己在尝试的过程中遇到了一些问题:

(1)在编译ffmpeg时采用MT(d)进行编译时出现了很多问题,所以编译ffmpeg还是使用MD(d)方式,但是呢webrtc默认编译的是MT(d),所以需要将webrtc修改为MD(d),修改方式具体见前面;

(2)在使用ffmpeg_deps.sln生成库时,务必选择编译动态库,在使用ffmpeg静态库时则会出现符号重定义的问题,具体如下:

原因就是webrtc所依赖的第三方库中也使用了libvp8(highbd_variance_sse2.obj),而ffmpeg的静态库libavcodec.lib中也包含了highbd_variance_sse2.obj的定义,因此出现了冲突,论据如下:

webrtc中的证据:

2.3.2 解决步骤

假设已经准备好了ffmpeg的动态库,后续的步骤主要如下:

2.3.2.1 拷贝文件

将ffmpeg_deps.sln生成的如下图中的文件拷贝到webrtc的指定目录,具体如下:

D:\webrtc-checkout\src\third_party\ffmpeg_smp_release_x64目录是新创建的,为的就是与之前的ffmpeg区别开来;

拷贝动态库文件

拷贝头文件

2.3.2.2 修改gn文件

修改D:\webrtc-checkout\src\modules\video_coding\BUILD.gn文件

修改内容罗列如下:

rtc_static_library("webrtc_h264") {
  visibility = [ "*" ]
  sources = [
    "codecs/h264/h264.cc",
    "codecs/h264/h264_color_space.cc",
    "codecs/h264/h264_color_space.h",
    "codecs/h264/h264_decoder_impl.cc",
    "codecs/h264/h264_decoder_impl.h",
    "codecs/h264/h264_encoder_impl.cc",
    "codecs/h264/h264_encoder_impl.h",
    "codecs/h264/include/h264.h",
  ]

  if (!is_clang) {
  #设置头文件路径
    include_dirs = [ "//third_party/ffmpeg_smp_release_x64/include" ]
    libs = [
   # 设置引用库
       "//third_party/ffmpeg_smp_release_x64/bin/avcodec.lib",
       "//third_party/ffmpeg_smp_release_x64/bin/avdevice.lib",
       "//third_party/ffmpeg_smp_release_x64/bin/avfilter.lib",
       "//third_party/ffmpeg_smp_release_x64/bin/avformat.lib",
       "//third_party/ffmpeg_smp_release_x64/bin/avutil.lib",
       "//third_party/ffmpeg_smp_release_x64/bin/swresample.lib",
       "//third_party/ffmpeg_smp_release_x64/bin/swscale.lib",
    ]
  }

  defines = []
  deps = [
    ":video_codec_interface",
    ":video_coding_utility",
    "../../api/video:video_frame",
    "../../api/video:video_frame_i010",
    "../../api/video:video_frame_i420",
    "../../api/video:video_rtp_headers",
    "../../api/video_codecs:video_codecs_api",
    "../../common_video",
    "../../media:rtc_h264_profile_id",
    "../../media:rtc_media_base",
    "../../rtc_base",
    "../../rtc_base:checks",
    "../../rtc_base/system:rtc_export",
    "../../system_wrappers:field_trial",
    "../../system_wrappers:metrics",
    "//third_party/abseil-cpp/absl/strings",
    "//third_party/abseil-cpp/absl/types:optional",
    "//third_party/libyuv",
  ]

  if (rtc_use_h264) {
    deps += [
      #"//third_party/ffmpeg",
      "//third_party/openh264:encoder",
    ]
    if (!build_with_mozilla) {
      deps += [ "../../media:rtc_media_base" ]
    }
  }
}

截止到这里虽然可以编译成功了,但是还有其他的问题,虽然这里替换成了自己编译的ffmpeg的x64动态库,但是webrtc的代码中所引用的头文件还是之前的ffmpeg的路径,如果不修改在运行的时候就会出现崩溃,所以还需要修改源码,具体见2.3.2.3小节;

2.3.2.3 修改webrtc源码中对ffmpeg头文件的引用

至此就可以编译通过所有的exe,但是还不可以使用peerconnection_client.exe验证H264的功能,需要修改SDP来提高H264的优先级;

注意:

由于自己所使用的ffmpeg版本问题(相较于webrtc-m79的代码来说ffmpeg的版本太新了),还出现了avcodec_find_decoder的问题,由于avcodec_find_decoder现在返回的是const AVCodec*,而webrtc-m79中没有进行强制类型转换导致编译错误,需要进行一个简单的修改即可:

AVCodec* codec = avcodec_find_decoder(av_context_->codec_id);

修改为:

AVCodec* codec = const_cast<AVCodec*>(avcodec_find_decoder(av_context_->codec_id));

3 提高H264优先级

修改后的代码如下:

std::vector<SdpVideoFormat> InternalEncoderFactory::GetSupportedFormats()
    const {
  std::vector<SdpVideoFormat> supported_codecs;
  for (const webrtc::SdpVideoFormat& format : webrtc::SupportedH264Codecs())
    supported_codecs.push_back(format);
  supported_codecs.push_back(SdpVideoFormat(cricket::kVp8CodecName));
  for (const webrtc::SdpVideoFormat& format : webrtc::SupportedVP9Codecs())
    supported_codecs.push_back(format);
  return supported_codecs;
}

4 两个peerconnection_client进行验证

运行peerconnection_client.exe,别忘了拷贝其所依赖的动态库:

测试效果如下:

5 web端与peerconnection_client测试

若使用web与peerconnection_client进行测试,则需要注意,若web端发送offer来启动媒体协商过程,此时传输的仍然是VP8编码,原因是:

web端offer中描述自己最高优先接收的是VP8,接收offer的peerconnection_client端会在WebRtcVideoChannel::GetChangedSendParameters中通过调用SelectSendVideoCodecs来对比自己能提供的编码和offer期望的编码,会优先匹配offer中具有较高优先级的VP8编码,在自己修改的代码中InternalEncoderFactory::GetSupportedFormats中只是将H264的优先级提高了而已(((这个H264优先级的提高在本端作为offer端的时候可以让对端优先匹配该编码))),后面又加上了对VP8和VP9的支持,所以当offer端最高优先级的VP8能在对端被支持的时候,就会优先选择VP8格式来匹配offer端;也正是这个原因在使用两个peerconnection_client进行测试的时候不会出现这个问题,因为二者都是将接收H264设置为最高优先级;

当然若peerconnection_client.exe发送offer来启动媒体协商过程就不存在这个问题了,因为H264就是它的最高优先级接收的视频编码格式。

参考链接

[1] webrtc 4577版本vs编译_tusong86的博客-CSDN博客

[2] 创建ffmpeg vs2019工程_hclbeloved的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/101539.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【docker】运行redis

拉取redis镜像 有多种选择&#xff1a; redis&#xff08;基础版&#xff09;redis/redis-stack&#xff08;包含redis stack server和RedisInsight&#xff09;redis/redis-stack-server&#xff08;仅包含redis stack server&#xff09; docker pull redis docker pull r…

C语言——指针基本语法

概述 内存地址 在计算机内存中&#xff0c;每个存储单元都有一个唯一的地址(内存编号)。 通俗理解&#xff0c;内存就是房间&#xff0c;地址就是门牌号 指针和指针变量 指针&#xff08;Pointer&#xff09;是一种特殊的变量类型&#xff0c;它用于存储内存地址。 指针的实…

【混合时变参数系统参数估计算法】使用范数总和正则化和期望最大化的混合时变参数系统参数估计算法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

图像处理简介

目录 基本术语 1 .图像(image) 1.1 像素(Pixel) 1.2 颜色深度&#xff08;Color Depth&#xff09; 1.3 分辨率&#xff08;Resolution&#xff09; 1.4 像素宽高比&#xff08;Pixel Aspect Ratio&#xff09; 1.5 帧率(FPS) 1.6 码率&#xff08;BR&#xff09; 1. …

Vue中如何为Echarts统计图设置数据

在前端界面接收后端数据后&#xff0c;将数据赋值给ECharts中的data时出现了&#xff0c;数据读取失败的问题&#xff08;可能是由于数据渲染的前后顺序问题&#xff09;。后通过如下方式进行了解决&#xff1a; 1、接下来将介绍UserController中的countUsers方法&#xff0c;…

Liunx系统编程:信号量

一. 信号量概述 1.1 信号量的概念 在多线程场景下&#xff0c;我们经常会提到临界区和临界资源的概念&#xff0c;如果临界区资源同时有多个执行流进入&#xff0c;那么在多线程下就容易引发线程安全问题。 为了保证线程安全&#xff0c;互斥被引入&#xff0c;互斥可以保证…

redis面试题二

redis如何处理已过期的元素 常见的过期策略 定时删除&#xff1a;给每个键值设置一个定时删除的事件&#xff0c;比如有一个key值今天5点过期&#xff0c;那么设置一个事件5点钟去执行&#xff0c;把它数据给删除掉&#xff08;优点&#xff1a;可以及时利用内存及时清除无效数…

华为Mate60低调发布,你所不知道的高调真相?

华为Mate60 pro 这两天的劲爆新闻想必各位早已知晓&#xff0c;那就是华为Mate60真的来了&#xff01;&#xff01;&#xff01;并且此款手机搭载了最新国产麒麟9000s芯片&#xff0c;该芯片重新定义了手机性能的巅峰。不仅在Geekbench测试中表现出色&#xff0c;还在实际应用…

CTFhub-SSRF-内网访问

CTFHub 环境实例 | 提示信息 http://challenge-8bf41c5c86a8c5f4.sandbox.ctfhub.com:10800/?url_ 根据提示&#xff0c;在url 后门添加 127.0.0.1/flag.php http://challenge-8bf41c5c86a8c5f4.sandbox.ctfhub.com:10800/?url127.0.0.1/flag.php ctfhub{a6bb51530c8f6be0…

基于深度学习的三维重建从入门实战教程 原理讲解 源码解析 实操教程课件下载

传统的重建方法是使用光度一致性等来计算稠密的三维信息。虽然这些方法在理想的Lambertian场景下,精度已经很高。 但传统的局限性,例如弱纹理,高反光和重复纹理等,使得重建困难或重建的结果不完整。 基于学习的方法可以引入比如镜面先验和反射先验等全局语义信息,使匹配…

elementui tree 层级过多时,高亮状态无法选满整行

问题&#xff1a; 如上图所示&#xff0c;官方的tree组件&#xff0c;在层级很多时 elementui -tree 的高亮状态并没有选中整行。 &#xff08;衍生库 vue-easy-tree 也会出现此问题&#xff09; 原因&#xff1a; &#xff08;没有查看源码&#xff0c;只是根据dom简单定位…

Echart笔记

Echart笔记 柱状图带背景色的柱状图将X与Y轴交换制作为进度条 柱状图 带背景色的柱状图 将X与Y轴交换制作为进度条 //将X与Y轴交换制作为进度条 option { xAxis: {type: value,min:0,max:100,show:false,//隐藏x轴},yAxis: {type: category,data:[进度条],show:false,//隐…

Citespace、vosviewer、R语言的文献计量学 、SCI

文献计量学是指用数学和统计学的方法&#xff0c;定量地分析一切知识载体的交叉科学。它是集数学、统计学、文献学为一体&#xff0c;注重量化的综合性知识体系。特别是&#xff0c;信息可视化技术手段和方法的运用&#xff0c;可直观的展示主题的研究发展历程、研究现状、研究…

URL重定向漏洞

URL重定向漏洞 1. URL重定向1.1. 漏洞位置 2. URL重定向基础演示2.1. 查找漏洞2.1.1. 测试漏洞2.1.2. 加载完情况2.1.3. 验证漏洞2.1.4. 成功验证 2.2. 代码修改2.2.1. 用户端代码修改2.2.2. 攻击端代码修改 2.3. 利用思路2.3.1. 用户端2.3.1.1. 验证跳转 2.3.2. 攻击端2.3.2.1…

使用正则表达式在中英文之间添加空格

有时为了排版需要&#xff0c;我们可能需要在文章的中英文之间添加空格&#xff0c;特别是中文中引用了英文单词时&#xff0c;这种情况使用正则表达式整体修订是最明智的做法。首先&#xff0c;推荐使用在线的正则表格式工具&#xff1a;https://regex101.com/ , 该工具非常强…

LeetCode-53-最大子数组和-贪心算法

贪心算法理论基础&#xff1a; 局部最优推全局最优 贪心无套路~ 没有什么规律~ 重点&#xff1a;每个阶段的局部最优是什么&#xff1f; 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#…

煤矿监管电子封条算法

煤矿监管电子封条算法基于yolov5网络模型深度学习框架&#xff0c;先进技术的创新举措&#xff0c;煤矿监管电子封条算法通过在现场运料运人井口、回风井口、车辆出入口等关键位置进行人员进出、人数变化和设备开停等情况的识别和分析。YOLO检测速度非常快。标准版本的YOLO可以…

PY32F003F18P单片机概述

PY32F003F18P单片机是普冉的一款ARM微控制器&#xff0c;内核是Cortex-M0。这个单片机的特色&#xff0c;就是价格便宜&#xff0c;FLASH和SRAM远远超过8位单片机&#xff0c;市场竞争力很强大。 一、硬件资源&#xff1a; 1)、FLASH为64K字节&#xff1b; 2)、SRAM为8K字节&…

本地开机启动jar

1&#xff1a;首先有个可运行的jar包 本地以ruiyi代码为例打包 2&#xff1a;编写bat命令---命名为.bat即可 echo off java -jar D:\everyDay\test\RuoYi\target\RuoYi.jar 3&#xff1a;设置为开机自启动启动 快捷键winr----输入shell:startup---打开启动文档夹 把bat文件复…

NTP时钟同步服务器

目录 一、什么是NTP&#xff1f; 二、计算机时间分类 三、NTP如何工作&#xff1f; 四、NTP时钟同步方式&#xff08;linux&#xff09; 五、时间同步实现软件&#xff08;既是客户端软件也是服务端软件&#xff09; 六、chrony时钟同步软件介绍 七、/etc/chrony.conf配置文件介…