SILK : SILK_RTP_PayloadFormat 中文翻译

本文详细介绍了Skype开发的SILK语音频编解码器,包括其高度可扩展性特点、不同音频带宽模式及应用场景、自适应采样频率与网络码率特性、不连续传输模式及前向差错纠正机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于本备忘录

 

    本文件可能不会发布修正版本等后续工作。请注意SILK 仍然处在测试阶段,所以SILK 及其RTP 负载格式和文件存储格式都可能改变。如有疑问,请联系 silksupport@skype.net

 

版权声明

   

    版权 2009-2010,版权归Skype 所有

 

摘要

 

    本文件定义了将SILK 语音频编码数据打包所用的实时传输协议(RTP)负载格式和文件存储格式,这些数据对于以最兼容的方式实现SILK 是必不可少的。并进一步描述了RTP 负载格式和文件存储格式的媒体类型注册。

 

目录

   

   

   

1.    简介

SILK 是Skype 内部开发的一个语音频编解码器,作为Skype 到Skype 调用的默认编解码器。SILK 在音频带宽、网络码率和复杂度等方面的高度可扩展性使其成为可选择多种模式和应用的编解码器。

Skype 鼓励第三方合作伙伴组织(3GPP)在可能与Skype 互操作的网络中采用SILK。因此,本文件定义了将SILK 语音频编码数据打包所用的RTP 负载格式和文件存储格式,这些数据是以最兼容方式实现SILK 必不可少的。本文件进一步描述了RTP 负载格式和文件存储格式媒体类型注册。

关于SILK 的更多信息可以通过以下链接获得:

https://developer.skype.com/silk

 

2.    本文件使用的公约、定义和缩略语

本文件中出现的关键词“MUST”,“MUST NOT”,“REQUIRED”,“SHALL”,“SHALL NOT”,“SHOULD”,“SHOULD NOT”,“RECOMMEDED”,“MAY”,“OPTIONAL”的解释参见RFC 2119 [1]。

定义和缩略词:

CPU       ——   中央处理单元

IP      ——   网络协议

MTU       ——   最大传输单元

PSTN   ——   公共交换电话网

Samples ——   语音或音频采样点

SDP    ——   会话描述协议

 

3.    SILK 编解码器

SILK 语音频编解码器在音频带宽、网络码率和复杂度等方面具有高度的可扩展性。

SILK 支持四种不同的音频带宽:窄带8000 Hz 采样率,中带12000 Hz 采样率,宽带16000 Hz 采样率,超宽带24000 Hz 采样率。窄带模式应该(SHOULD)只用于PSTN 网络的接口或者用在不支持大于8000 Hz 采样率的低端设备上。中带模式应该(SHOULD)用于不支持大于12000 Hz 采样率的更低端设备或者严重的网络带宽限制的条件下(例如无线设备)。宽带模式应该(SHOULD)用于所有不支持大于16000 Hz 采样率的所有网络协议平台。超宽带模式应该(SHOULD)用于所有支持24000 Hz 或者更高采样率的平台。

平均目标网络码率在表1 对应音频带宽下规定的范围内是可变的。平均网络目标码率可以实时定义和修正,而实际码率依赖于输入信号,且随时间而改变。实际码率可能高于或低于表1 规定的自适应目标码率。推荐采用表中码率范围的上限。

 

表1. fs 代表以赫兹为单位的采样率,BR 代表以千位每秒为单位的自适应目标码率范围

 

Fs (Hz)

BR (kbps)

窄带

8000

5 – 20

中带

12000

7 – 25

宽带

16000

8 – 30

超宽带

24000

20 – 40

 

复杂度可扩展用于实时优化CPU 资源,多用于与网络码率的权衡。

SILK 内部帧长为20 ms。SILK 编码器可以设置为捆绑5 个内部帧为一个输出帧,允许编码语音频数据的帧长为20,40,60,80,100 ms。表2 显示了不同帧长和采样率时一帧语音或者音频包含的采样点数。

 

表2. 不同帧长和采样率时,一帧包含的采样点数

帧长

20 ms

40 ms

60 ms

80 ms

100 ms

窄带采样点

160

320

480

640

800

中带采样点

240

480

720

960

1200

宽带采样点

320

640

960

1280

1600

超宽带采样点

480

960

1440

1920

2400

 

SILK 操作在非常低的算法延迟,包括算法打包延迟(例如20,40,60,80,100 ms)加上5 ms 前瞻延迟。

 

3.1.自适应采样频率

SILK 编码的语音频信号内部采样率可以随着传输时间而变化,这可能在以下两种情况下发生。

第一种情况是,SILK 提供一种内部逻辑,决定自动将编码的语音频信号内部采样率调整到最有效的采样率,这个最有效采样率取决于输入信号和信道容量信息。这种内部逻辑使得SILK 支持拥塞控制和网络负荷管理。

第二种情况是,SILK 提供手动设置编码的语音频信号最大内部采样率的API 功能。这个最大内部采样率不能(MUST NOT)被设置高于呼叫建立协商时商定的采样率,这是因为SILK 的早期版本不能解码内部采样率高于解码端输出采样率(解码器API 采样率)的信号。

对于以上两种情况,只有被编码成码流的语音频信号的内部采样率被切换时,SILK 编码器输入的语音频信号和解码器输出的语音频信号的采样率才能单独设置而互不影响。

会话建立的时候,解码端应该(SHOULD)将系统可以利用的所有采样率(率参数)发信号给给编码端

 

3.2.自适应网络码率

SILK 编码器可以设置不同的平均目标码率输出编码的语音频数据。规定的平均目标码率是为积极信号(例如非静音帧)设置的,因此每一帧的实际码率根据数据语音频信号的感知重要性而变化。平均目标码率可以以帧为单位进行调整,这使SILK 支持拥塞控制和网络负荷管理。

为了有效的实现这些,必须提供信道容量和存储设备的相关信息。这些信息可以通过多种渠道获得,但不再本文件讨论范围。

当无法获得信道容量信息时,SILK 可以以固定的平均目标码率运行。这个固定的平均目标码率必须谨慎选择,因为超过信道容量时可能导致额外的延迟和语音帧丢失。除非最宽带宽网络接口技术的信道限制是已知的,否则推荐使用表1 中提供的最大平均目标码率达到最好的语音音质。

 

3.3.不连续传输(DTX)

如本文件3.2 节所述,SILK 编解码器是码率自适应的。对于特定的输入信号,比如静音周期,码率会被自动削减。在连续传输模式下,当输入信号允许的时候,编码器会削减码率,但是,到接收器的传输不会被中断。因此,接收到的信号在全部传输过程中使码率最小化但保持较高水平的音质。

在SILK 的平均码率需要进一步削减的情况下,SILK 编码器可以设置成不连续传输(DTX),此时部分编码信号,即输入语音频信号的静音周期,不被传送到接收端。

在接收端,没有传送的部分将被SILK 解码器当作丢失帧处理,即产生舒适噪声信号代替没有传送的语音频信号部分。

SILK 的不连续传输模式的语音频音质会比连续模式稍差。因此,推荐(RECOMMENDED)使用SILK 的连续模式,除非网络带宽的限制比较严格。

 

3.4.前向差错纠正(FEC)

SILK 编解码器允许在SILK 码流中嵌入“带内”前向差错纠正(FEC)数据。这种FEC 方案将前一帧(n-1)或者前两帧(n-2)的冗余信息加到当前帧(n)。对于每一帧,编码器根据以下信息决定是否使用FEC :(1)外部提供的信道丢包率估计值;(2)外部提供的信道容量估计值;(3)语音频信号对丢包的敏感度;(4)接收端解码器是否显示可以利用“带内”FEC 信息。发送“带内”FEC 信息的决定完全受编码器控制,因此不需要关于负载或存储格式的特殊注意事项。

在接收端,当某一帧丢失而未来帧可接收到的时候,解码器可以利用这些附加信息。为了使用FEC 数据,抖动缓冲区需要提供包含SILK 未来帧的负载和相对SIK 上一解码帧偏移量的信息。一个特殊的API 函数可以搜索可用的FEC 数据,如果搜索成功的话,可以作为当前丢失帧提供给解码器。

如果这种FEC 方案没有在接收端实现的话,FEC不应该(SHOULD NOT)被使用,因为它将导致网络带宽的低效使用。解码器支持FEC 的话,应该(SHOULD)在会话建立的时候显示。

出现了链接错误: ld.lld: error: undefined symbol: webrtc::NetEq::Config::Config() >>> referenced by test1.cpp:115 (packages/apps/zorro/neteq/test1.cpp:115) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(CreateNetEq(webrtc::Clock*)) ld.lld: error: undefined symbol: webrtc::CreateBuiltinAudioDecoderFactory() >>> referenced by test1.cpp:120 (packages/apps/zorro/neteq/test1.cpp:120) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(CreateNetEq(webrtc::Clock*)) ld.lld: error: undefined symbol: webrtc::DefaultNetEqFactory::DefaultNetEqFactory() >>> referenced by test1.cpp:123 (packages/apps/zorro/neteq/test1.cpp:123) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(CreateNetEq(webrtc::Clock*)) ld.lld: error: undefined symbol: webrtc::DefaultNetEqFactory::CreateNetEq(webrtc::NetEq::Config const&, rtc::scoped_refptr<webrtc::AudioDecoderFactory> const&, webrtc::Clock*) const >>> referenced by test1.cpp:124 (packages/apps/zorro/neteq/test1.cpp:124) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(CreateNetEq(webrtc::Clock*)) ld.lld: error: undefined symbol: webrtc::DefaultNetEqFactory::~DefaultNetEqFactory() >>> referenced by test1.cpp:132 (packages/apps/zorro/neteq/test1.cpp:132) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(CreateNetEq(webrtc::Clock*)) ld.lld: error: undefined symbol: webrtc::NetEq::Config::~Config() >>> referenced by test1.cpp:132 (packages/apps/zorro/neteq/test1.cpp:132) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(CreateNetEq(webrtc::Clock*)) ld.lld: error: undefined symbol: rtc::webrtc_checks_impl::FatalLog(char const*, int, char const*, rtc::webrtc_checks_impl::CheckArgType const*, ...) >>> referenced by checks.h:254 (packages/apps/zorro/neteq/include/rtc_base/checks.h:254) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(CreateNetEq(webrtc::Clock*)) ld.lld: error: undefined symbol: webrtc::DefaultNetEqFactory::~DefaultNetEqFactory() >>> referenced by test1.cpp:132 (packages/apps/zorro/neteq/test1.cpp:132) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(CreateNetEq(webrtc::Clock*)) ld.lld: error: undefined symbol: webrtc::NetEq::Config::~Config() >>> referenced by test1.cpp:132 (packages/apps/zorro/neteq/test1.cpp:132) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(CreateNetEq(webrtc::Clock*)) ld.lld: error: undefined symbol: webrtc::SdpAudioFormat::SdpAudioFormat(std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, unsigned long, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >&&) >>> referenced by test1.cpp:140 (packages/apps/zorro/neteq/test1.cpp:140) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(RegisterCodec(webrtc::NetEq*)) ld.lld: error: undefined symbol: webrtc::SdpAudioFormat::~SdpAudioFormat() >>> referenced by test1.cpp:138 (packages/apps/zorro/neteq/test1.cpp:138) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(RegisterCodec(webrtc::NetEq*)) ld.lld: error: undefined symbol: webrtc::SdpAudioFormat::SdpAudioFormat(std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, unsigned long) >>> referenced by test1.cpp:145 (packages/apps/zorro/neteq/test1.cpp:145) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(RegisterCodec(webrtc::NetEq*)) ld.lld: error: undefined symbol: webrtc::SdpAudioFormat::~SdpAudioFormat() >>> referenced by test1.cpp:143 (packages/apps/zorro/neteq/test1.cpp:143) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(RegisterCodec(webrtc::NetEq*)) ld.lld: error: undefined symbol: webrtc::SdpAudioFormat::SdpAudioFormat(std::__1::basic_string_view<char, std::__1::char_traits<char> >, int, unsigned long) >>> referenced by test1.cpp:150 (packages/apps/zorro/neteq/test1.cpp:150) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(RegisterCodec(webrtc::NetEq*)) ld.lld: error: undefined symbol: webrtc::SdpAudioFormat::~SdpAudioFormat() >>> referenced by test1.cpp:148 (packages/apps/zorro/neteq/test1.cpp:148) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(RegisterCodec(webrtc::NetEq*)) ld.lld: error: undefined symbol: webrtc::SdpAudioFormat::~SdpAudioFormat() >>> referenced by test1.cpp:0 (packages/apps/zorro/neteq/test1.cpp:0) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(RegisterCodec(webrtc::NetEq*)) ld.lld: error: undefined symbol: webrtc::SdpAudioFormat::~SdpAudioFormat() >>> referenced by test1.cpp:138 (packages/apps/zorro/neteq/test1.cpp:138) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(RegisterCodec(webrtc::NetEq*)) ld.lld: error: undefined symbol: webrtc::RTPHeader::RTPHeader() >>> referenced by test1.cpp:156 (packages/apps/zorro/neteq/test1.cpp:156) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(ProcessRtpPacket(webrtc::NetEq*, webrtc::RtpPacket const&)) ld.lld: error: undefined symbol: rtc::webrtc_logging_impl::Log(rtc::webrtc_logging_impl::LogArgType const*, ...) >>> referenced by logging.h:398 (packages/apps/zorro/neteq/include/rtc_base/logging.h:398) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(ProcessRtpPacket(webrtc::NetEq*, webrtc::RtpPacket const&)) ld.lld: error: undefined symbol: rtc::LogMessage::IsNoop(rtc::LoggingSeverity) >>> referenced by logging.h:545 (packages/apps/zorro/neteq/include/rtc_base/logging.h:545) >>> out/target/product/rk3399_Android10/obj/EXECUTABLES/neteq_rtpplay_intermediates/test1.o:(bool rtc::LogMessage::IsNoop<(rtc::LoggingSeverity)2>()) ld.lld: error: too many errors emitted, stopping now (use -error-limit=0 to see all errors) clang-9: error: linker command failed with exit code 1 (use -v to see invocation) 10:53:28 ninja failed with: exit status 1
最新发布
08-03
<think>我们遇到了多个链接错误,这些错误表明在链接阶段找不到某些符号的定义。这些符号主要来自WebRTC库,包括NetEq相关的类、工厂函数、SdpAudioFormat、RTPHeader以及日志系统等。错误原因可能是: 1. 没有正确链接WebRTC库。 2. 使用的WebRTC版本与头文件不匹配。 3. 在构建配置中没有包含必要的源文件或库。 解决方案: 1. 确保在构建系统中正确链接WebRTC库。例如,在Android.mk或CMakeLists.txt中添加WebRTC库。 2. 检查WebRTC的版本,确保使用的头文件和库文件版本一致。 3. 确认在构建目标时包含了所有必要的依赖。 下面是一个示例,展示如何在Android.mk中添加WebRTC库(假设WebRTC被预编译为静态库): ```makefile # 示例Android.mk片段 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := neteq_rtpplay # 添加源文件 LOCAL_SRC_FILES := test1.cpp # 添加WebRTC库 LOCAL_STATIC_LIBRARIES := libwebrtc # 如果需要,添加其他依赖 LOCAL_LDLIBS := -llog -lOpenSLES # 包含头文件路径 LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/include \ path/to/webrtc/include include $(BUILD_EXECUTABLE) # 预编译WebRTC静态库 include $(CLEAR_VARS) LOCAL_MODULE := libwebrtc LOCAL_SRC_FILES := path/to/webrtc/lib/libwebrtc.a include $(PREBUILT_STATIC_LIBRARY) ``` 如果使用CMake,则需要在CMakeLists.txt中链接WebRTC库: ```cmake cmake_minimum_required(VERSION 3.4.1) # 添加可执行文件 add_executable(neteq_rtpplay test1.cpp ) # 包含WebRTC头文件 include_directories(path/to/webrtc/include) # 链接WebRTC库 target_link_libraries(neteq_rtpplay path/to/webrtc/lib/libwebrtc.a log OpenSLES ) ``` 另外,注意错误中提到的符号可能位于WebRTC的不同模块中。例如: - `webrtc::NetEq::Config` 可能在neteq模块中。 - `webrtc::CreateBuiltinAudioDecoderFactory` 可能在audio/decoder模块中。 - `webrtc::DefaultNetEqFactory` 可能在neteq/default_neteq_factory中。 - `rtc::LogMessage` 在rtc_base/logging中。 因此,确保链接的WebRTC库包含了这些模块。如果WebRTC是自行编译的,请检查编译配置是否包含了这些模块。 如果问题仍然存在,可以尝试以下步骤: 1. 检查WebRTC库是否包含这些符号:使用nm工具查看库文件。 2. 确认在代码中包含了正确的头文件。 3. 如果使用的WebRTC版本较新,注意某些API可能已经废弃或更改,需要调整代码。 例如,在较新的WebRTC版本中,`DefaultNetEqFactory`可能已经被移除,建议使用`CreateNetEq`工厂函数。可以查看WebRTC的头文件或文档确认。 由于错误信息中还提到了`SdpAudioFormat`的构造函数和析构函数,请确保在代码中正确使用了`SdpAudioFormat`。示例: ```cpp // 创建SdpAudioFormat对象 webrtc::SdpAudioFormat opus_format("opus", 48000, 2, {{"stereo", "1"}}); ``` 最后,注意链接顺序,确保依赖库的顺序正确(被依赖的库放在后面)。 如果以上方法不能解决问题,可能需要重新编译WebRTC,并确保在编译时启用了所需的模块。 由于错误信息较多,建议先解决第一个未定义符号的问题,因为后面的错误可能是由前面的错误导致的。 这里提供一个可能的代码修正示例(假设代码中使用了`DefaultNetEqFactory`,但新版本中已废弃): 在WebRTC的较新版本(如M84之后)中,创建NetEq的方式可能已经改变。可以尝试使用`CreateNetEq`函数: ```cpp #include "api/neteq/neteq.h" #include "api/neteq/default_neteq_controller_factory.h" #include "modules/audio_coding/neteq/default_neteq_factory.h" std::unique_ptr<webrtc::NetEq> CreateNetEq(webrtc::Clock* clock) { webrtc::NetEq::Config config; // 配置config auto decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory(); webrtc::DefaultNetEqFactory factory; return factory.CreateNetEq(config, decoder_factory, clock); } ``` 但是,如果`DefaultNetEqFactory`已经被移除,那么可能需要使用`CreateNetEq`的工厂函数(如果存在)或者使用新的方式。 根据WebRTC的最新代码(如M96),创建NetEq的方式如下: ```cpp #include "api/neteq/default_neteq_controller_factory.h" #include "api/neteq/neteq_factory.h" #include "modules/audio_coding/neteq/neteq_impl.h" std::unique_ptr<webrtc::NetEq> CreateNetEq( const webrtc::NetEq::Config& config, webrtc::Clock* clock, const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory) { webrtc::NetEqFactory::Config neteq_factory_config; neteq_factory_config.neteq_config = config; neteq_factory_config.clock = clock; neteq_factory_config.decoder_factory = decoder_factory; return webrtc::CreateNetEq(neteq_factory_config, std::make_unique<webrtc::DefaultNetEqControllerFactory>()); } ``` 因此,需要根据实际使用的WebRTC版本调整代码。 由于错误信息中还有日志相关的未定义符号,请确保链接了WebRTC的base库(包含日志系统)。 综上所述,解决链接错误的关键是: 1. 确保正确链接WebRTC库及其所有依赖。 2. 根据WebRTC版本调整代码。 如果问题仍然存在,请提供使用的WebRTC版本和构建环境信息,以便进一步分析。 §§相关问题§§: 1. 在Android中如何正确链接预编译的WebRTC静态库? 2. WebRTC中NetEq的主要功能是什么? 3. 如何在不同版本的WebRTC中创建NetEq实例? 4. 如何处理WebRTC中未定义的符号错误?</think>### 解决 WebRTC 链接错误的分析与方案 这些链接错误表明您的代码引用了 WebRTC 中的符号,但链接器找不到它们的实现。这通常由以下原因引起: 1. **缺少必要的 WebRTC 库链接** 2. **使用了不兼容的 WebRTC 版本** 3. **构建配置中缺少关键编译选项** 4. **头文件与库文件版本不匹配** ### 完整解决方案 #### 1. 确保正确链接 WebRTC 库(Android.mk 示例) ```makefile # Android.mk 配置 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := neteq_rtpplay LOCAL_SRC_FILES := test1.cpp # 关键:链接所有必需的 WebRTC 库 LOCAL_STATIC_LIBRARIES := \ libwebrtc_neteq \ libwebrtc_audio_decoder \ libwebrtc_rtc_base \ libwebrtc_system_wrappers \ libwebrtc_audio_coding # 包含 WebRTC 头文件路径 LOCAL_C_INCLUDES := \ $(WEBRTC_ROOT)/src \ $(WEBRTC_ROOT)/src/api \ $(WEBRTC_ROOT)/src/modules/audio_coding \ $(WEBRTC_ROOT)/src/rtc_base # 启用 RTTI 和异常(WebRTC 需要) LOCAL_CPPFLAGS := -frtti -fexceptions # 链接系统库 LOCAL_LDLIBS := -llog -lOpenSLES include $(BUILD_EXECUTABLE) ``` #### 2. 更新 NetEq 创建代码(兼容最新 WebRTC API) ```cpp #include "api/neteq/neteq.h" #include "api/neteq/default_neteq_controller_factory.h" #include "modules/audio_coding/neteq/default_neteq_factory.h" std::unique_ptr<webrtc::NetEq> CreateNetEq(webrtc::Clock* clock) { // 1. 创建 NetEq 配置 webrtc::NetEq::Config config; config.enable_post_decode_vad = true; config.max_packets_in_buffer = 200; config.sample_rate_hz = 48000; // 2. 创建音频解码器工厂 rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory(); // 3. 使用新的工厂模式创建 NetEq webrtc::DefaultNetEqFactory factory; return factory.CreateNetEq(config, decoder_factory, clock); } ``` #### 3. 修复 SdpAudioFormat 使用方式 ```cpp #include "api/audio_codecs/audio_format.h" void RegisterCodec(webrtc::NetEq* neteq) { // 正确创建 SdpAudioFormat 对象 webrtc::SdpAudioFormat opus_format("opus", 48000, 2, { {"stereo", "1"}, {"usedtx", "0"} }); webrtc::SdpAudioFormat pcmu_format("pcmu", 8000, 1); webrtc::SdpAudioFormat pcma_format("pcma", 8000, 1); // 注册编解码器 neteq->RegisterPayloadType(opus_format, 111); // OPUS payload type 111 neteq->RegisterPayloadType(pcmu_format, 0); // PCMU payload type 0 neteq->RegisterPayloadType(pcma_format, 8); // PCMA payload type 8 // 注意:SdpAudioFormat 对象会在作用域结束时自动析构 } ``` #### 4. 修复 RTPHeader 初始化 ```cpp #include "api/rtp_headers.h" void ProcessRtpPacket(webrtc::NetEq* neteq, const webrtc::RtpPacket& packet) { // 正确初始化 RTPHeader webrtc::RTPHeader header; header.payloadType = packet.PayloadType(); header.sequenceNumber = packet.SequenceNumber(); header.timestamp = packet.Timestamp(); header.ssrc = packet.Ssrc(); header.numCSRCs = 0; // 处理 RTP 包 webrtc::NetEq::Packet neteq_packet; neteq_packet.payload_type = header.payloadType; neteq_packet.timestamp = header.timestamp; neteq_packet.payload = packet.payload().data(); neteq_packet.payload_length = packet.payload_size(); neteq->InsertPacket(neteq_packet); } ``` ### 关键问题分析 1. **NetEq::Config 构造函数问题**: - 新版本 WebRTC 中 `NetEq::Config` 是结构体而非类 - 解决方案:直接初始化结构体成员 ```cpp webrtc::NetEq::Config config = { .sample_rate_hz = 48000, .enable_post_decode_vad = true, .max_packets_in_buffer = 100 }; ``` 2. **DefaultNetEqFactory 使用问题**: - 确保使用最新工厂模式: ```cpp #include "modules/audio_coding/neteq/default_neteq_factory.h" webrtc::DefaultNetEqFactory factory; auto neteq = factory.CreateNetEq(config, decoder_factory, clock); ``` 3. **日志系统链接问题**: - 确保链接 `libwebrtc_rtc_base` 库 - 添加日志初始化代码: ```cpp #include "rtc_base/logging.h" int main() { rtc::LogMessage::LogToDebug(rtc::LS_INFO); RTC_LOG(LS_INFO) << "NetEq application started"; // ... } ``` ### 构建系统优化建议 1. **CMake 配置示例**: ```cmake cmake_minimum_required(VERSION 3.10) project(neteq_rtpplay) # 定位 WebRTC 库 find_package(WebRTC REQUIRED COMPONENTS neteq audio_decoder rtc_base ) add_executable(neteq_rtpplay test1.cpp) # 链接 WebRTC 库 target_link_libraries(neteq_rtpplay PRIVATE WebRTC::neteq WebRTC::audio_decoder WebRTC::rtc_base ) # 设置编译选项 target_compile_options(neteq_rtpplay PRIVATE -DWEBRTC_POSIX -DWEBRTC_LINUX -DWEBRTC_ANDROID -frtti -fexceptions ) ``` 2. **版本兼容性检查**: ```cpp // 检查 WebRTC 版本 #if defined(WEBRTC_VERSION) && (WEBRTC_VERSION > 8000000) // 使用新 API #include "api/neteq/default_neteq_controller_factory.h" #else // 旧版本兼容 #include "modules/audio_coding/neteq/neteq_impl.h" #endif ``` ### 错误处理最佳实践 ```cpp // 安全创建 NetEq 实例 std::unique_ptr<webrtc::NetEq> CreateNetEqSafe(webrtc::Clock* clock) { try { auto decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory(); if (!decoder_factory) { RTC_LOG(LS_ERROR) << "Failed to create audio decoder factory"; return nullptr; } webrtc::NetEq::Config config; config.sample_rate_hz = 48000; webrtc::DefaultNetEqFactory factory; return factory.CreateNetEq(config, decoder_factory, clock); } catch (const std::exception& e) { RTC_LOG(LS_ERROR) << "NetEq creation failed: " << e.what(); return nullptr; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值