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

FFmpeg6.1 RTSP推流报错:缺失sprop-parameter-sets求助

解决FFmpeg 6.1 RTSP推流时sprop-parameter-sets缺失的问题

错误原因

服务器返回的错误明确指出:当H264流使用packetization-mode=1(RTP分片传输模式)时,RTSP的SDP必须携带sprop-parameter-sets参数。该参数是H264的SPS(序列参数集)和PPS(图像参数集)的Base64编码值,用于客户端初始化解码器,属于强制要求项。

具体解决步骤

1. 确保SPS/PPS正确传入FFmpeg编码上下文

如果推流的是原始H264帧(无封装格式),必须主动将SPS和PPS数据赋值给AVCodecContext的extradata字段——FFmpeg依赖该字段生成SDP中的sprop参数:

// 假设已通过外部方式获取到SPS/PPS的二进制数据及长度
uint8_t *sps_data;
int sps_len;
uint8_t *pps_data;
int pps_len;

// 拼接SPS和PPS,赋值给extradata
int extradata_size = sps_len + pps_len;
codec_ctx->extradata = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!codec_ctx->extradata) {
    // 内存分配错误处理
}
memcpy(codec_ctx->extradata, sps_data, sps_len);
memcpy(codec_ctx->extradata + sps_len, pps_data, pps_len);
codec_ctx->extradata_size = extradata_size;

2. 显式设置AVDictionary参数

若仅设置extradata仍不生效,需手动将SPS/PPS转为Base64后,通过AVDictionary传入RTSP muxer:

  • 实现Base64编码函数(或使用可靠的第三方实现),将SPS、PPS二进制数据分别编码为Base64字符串;
  • 拼接成"base64_sps,base64_pps"格式,设置到字典中:
char *sps_b64 = base64_encode(sps_data, sps_len);
char *pps_b64 = base64_encode(pps_data, pps_len);
if (!sps_b64 || !pps_b64) {
    // 编码错误处理
}

char sprop_value[512];
snprintf(sprop_value, sizeof(sprop_value), "%s,%s", sps_b64, pps_b64);
av_dict_set(&opts, "sprop-parameter-sets", sprop_value, 0);
// 强制指定packetization-mode与服务器要求一致
av_dict_set(&opts, "packetization-mode", "1", 0);

// 释放Base64字符串内存
free(sps_b64);
free(pps_b64);

3. 排查FFmpeg编译配置

确保编译FFmpeg时启用了RTSP相关模块,避免因精简编译导致参数不生效:

./configure --enable-protocol=rtsp --enable-muxer=rtsp --enable-demuxer=rtsp

4. 验证SDP内容

修改完成后抓包查看RTSP协商阶段的SDP内容,确认是否包含如下字段:

a=fmtp:96 packetization-mode=1;sprop-parameter-sets=Z0IAKpZQFAFpwAAADACAAAAwDxQo9A==,aM48gA==

若存在该字段,则参数已生效,问题可解决。

完整代码片段示例

#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>

// 假设已实现Base64编码函数char* base64_encode(const uint8_t* data, int len);

int main() {
    AVFormatContext *ofmt_ctx = NULL;
    AVCodecContext *codec_ctx = NULL;
    AVDictionary *opts = NULL;
    const char *rtsp_url = "rtsp://your-server-url/stream";

    // ... 初始化输入流、获取SPS/PPS数据(sps_data, sps_len, pps_data, pps_len) ...

    // 配置编码上下文extradata
    int extradata_size = sps_len + pps_len;
    codec_ctx->extradata = av_mallocz(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
    memcpy(codec_ctx->extradata, sps_data, sps_len);
    memcpy(codec_ctx->extradata + sps_len, pps_data, pps_len);
    codec_ctx->extradata_size = extradata_size;

    // 设置RTSP推流参数
    char *sps_b64 = base64_encode(sps_data, sps_len);
    char *pps_b64 = base64_encode(pps_data, pps_len);
    char sprop_str[512];
    snprintf(sprop_str, sizeof(sprop_str), "%s,%s", sps_b64, pps_b64);
    av_dict_set(&opts, "sprop-parameter-sets", sprop_str, 0);
    av_dict_set(&opts, "packetization-mode", "1", 0);

    // 打开输出上下文
    int ret = avformat_open_output(&ofmt_ctx, rtsp_url, NULL, &opts);
    if (ret < 0) {
        char err_buf[AV_ERROR_MAX_STRING_SIZE];
        av_strerror(ret, err_buf, sizeof(err_buf));
        fprintf(stderr, "Open output failed: %s\n", err_buf);
        return -1;
    }

    // ... 后续流参数配置、推流逻辑 ...

    // 资源释放
    avformat_close_input(&ofmt_ctx);
    av_dict_free(&opts);
    av_freep(&codec_ctx->extradata);
    avcodec_free_context(&codec_ctx);

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 01:56:07