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
相关产品推荐
相关产品推荐

