在开发WebRTC的Android端时遇到一个奇怪的问题,Android端与PC端视频时听不到PC端的声音,其他一切都正常。通过分析,之前音视频工作都很正常,最近测试声音引擎时出现了该问题,本次测试增加了声音引擎的一些限制,如下:
audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair(AUDIO_ECHO_CANCELLATION_CONSTRAINT, "false"));
audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair(AUDIO_AUTO_GAIN_CONTROL_CONSTRAINT, "false"));
audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair(AUDIO_HIGH_PASS_FILTER_CONSTRAINT, "false"));
audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair(AUDIO_NOISE_SUPPRESSION_CONSTRAINT, "false"));
从代码没有发现有什么不妥的地方,只能先还原,屏蔽了上述代码再测试,一切又正常了。这下有的玩了,难道是WebRTC的声音引擎有bug?检查下视频连接的日志,发现一个显眼的红色error日志:“
Platform AEC state can't be modified while recording”
这个错误发生在交换SDP过程中,从错误的语义中可以大致判断出是声音引擎抛出来的。
在Android Studio中通过全局搜索的方式将问题定位到WebRtcAudioEffects类,该类是WebRTC处理音频效果的,而问题是下面这个方法抛出来的:
// Call this method to enable or disable the platform AEC. It modifies
// |shouldEnableAec| which is used in enable() where the actual state
// of the AEC effect is modified. Returns true if HW AEC is supported and
// false otherwise.
public boolean setAEC(boolean enable) {
Logging.d(TAG, "setAEC(" + enable + ")");
if (!canUseAcousticEchoCanceler()) {
Logging.w(TAG, "Platform AEC is not supported");
shouldEnableAec = false;
return false;
}
if (aec != null && (enable != shouldEnableAec)) {
Logging.e(TAG, "Platform AEC state can't be modified while recording");
return false;
}
shouldEnableAec = enable;
return true;
}
通过debug发现抛出该异常时由于shouldEnableAec 一直为false,而enable=ture,aec!=null。
思来想去还是去maven检查下libjingle的最新版本:http://mvnrepository.com/artifact/io.pristine/libjingle
发现最新版本为11139,而我们的项目采用的自己编译的,版本可能有差异,还不确定是否是版本差异导致的,那就先采用远程依赖的方式引入最新的版本测试下吧
compile 'io.pristine:libjingle:11139@aar'
将代码稍微调整了一下,经过测试发下一切正常,问题原因浮出水面,下面我们看下最新版本是怎样的:
public boolean setAEC(boolean enable) {
Logging.d("WebRtcAudioEffects", "setAEC(" + enable + ")");
if(!canUseAcousticEchoCanceler()) {
Logging.w("WebRtcAudioEffects", "Platform AEC is not supported");
this.shouldEnableAec = false;
return false;
} else if(this.aec != null && enable != this.shouldEnableAec) {
Logging.e("WebRtcAudioEffects", "Platform AEC state can\'t be modified while recording");
return false;
} else {
this.shouldEnableAec = enable;
return true;
}
}
细心看下肯定能发现判断语句在这里是闭环的,看来google的确已经发现问题并处理过了,好吧,看来又有工作要做了:编译最新版的libjingle了。