You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PJSUA2中onFrameReceived帧处理及Speex解码异常问题咨询

问题与解答

核心疑问

  • 问题1:onFrameReceived接收的帧是在抖动处理之前还是之后?
  • 问题2:若在抖动处理前接收,是否可获取每帧的RTP头信息以自行添加抖动缓冲区重排序?

解码异常问题

将帧送入Speex解码器时出现以下错误:

  • notification: Invalid mode encountered. The stream is corrupted.
  • notification: More than two wideband layers found. The stream is corrupted.

怀疑是帧未经过抖动缓冲、按网络到达顺序传入导致,处理代码如下:

void Analyzer::processFrame(pj::MediaFrame &frame) {
    spx_int16_t output[640];

    speex_bits_read_from(&m_speexbits, reinterpret_cast<char *>(frame.buf.data()), frame.size);
    int rc = speex_decode_int(m_speexstate,&m_speexbits,output);
    if (rc != 0) {
        LOG(LOG_ERR) << *this << " : speex decoder error: " << rc << std::endl;
    }

    // more processing....
}

关于抖动处理时机的解答

  1. 在PJMedia框架中,AudioMediaPort的onFrameReceived默认在抖动缓冲处理之前接收帧。抖动缓冲属于媒体流传输链路的后处理环节,原始RTP帧会先传递到媒体端口,再进入抖动缓冲做重排序、去抖动处理。
  2. 可以获取每帧的RTP头信息。你可将pj::MediaFrame转换为pj::RtpMediaFrame,或直接访问帧的底层RTP结构——PJMedia中MediaFrame的rtp字段包含序列号、时间戳等RTP头信息,足够实现自定义抖动缓冲区与帧重排序逻辑。

关于Speex解码异常的排查与解决

你的怀疑有合理性,但解码错误也可能由其他因素导致,可按以下步骤排查:

  1. 确认帧的顺序与完整性
    未经过抖动缓冲的帧会存在乱序、丢包情况,而Speex解码器对输入帧的顺序和完整性要求较高。你可通过RTP序列号验证帧的顺序,先实现简单的抖动缓冲:缓存一定数量的帧,按序列号排序后再送入解码器。
  2. 检查解码器初始化配置
    确保m_speexstate的初始化与编码端模式完全匹配:
    • 编码端用窄带(8kHz)、宽带(16kHz)或超宽带(32kHz)模式,解码器必须初始化对应模式,不能混用;
    • 若编码端使用多层编码(如Speex的VBR或多层窄带/宽带),需确保解码器开启对应支持。
  3. 验证输入帧格式
    • 确认frame.buf.data()中的数据是纯Speex编码负载,不含RTP头或其他冗余数据。如果onFrameReceived传入的是带RTP头的帧,需先剥离RTP头再送入解码器;
    • 检查frame.size是否与Speex帧实际大小匹配,避免传入不完整的帧数据。
  4. 重置SpeexBits状态
    每次调用speex_bits_read_from前,建议调用speex_bits_reset(&m_speexbits),避免旧数据残留干扰新帧解码。

修改后的示例代码:

void Analyzer::processFrame(pj::MediaFrame &frame) {
    spx_int16_t output[640];

    // 重置SpeexBits状态,清除残留数据
    speex_bits_reset(&m_speexbits);
    // 读取纯Speex负载数据
    speex_bits_read_from(&m_speexbits, reinterpret_cast<char *>(frame.buf.data()), frame.size);
    int rc = speex_decode_int(m_speexstate, &m_speexbits, output);
    if (rc != 0) {
        LOG(LOG_ERR) << *this << " : speex decoder error: " << rc << std::endl;
    }

    // more processing....
}

内容的提问来源于stack exchange,提问作者Gavin Murphy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 09:43:21