intel qsv ffmpeg 编码问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yoyoluck
V2EX    FFmpeg

intel qsv ffmpeg 编码问题

  •  
  •   yoyoluck 3 小时 45 分钟前 210 次点击

    有朋友搞过 ffmpeg qsv 硬件编码吗? 最近有一个任务,需要将音视频经过 ffmpeg 库编码成 h264/h265 之后送到海康的硬盘录像机 目前遇到问题是 使用 libx264 软编码的数据通过 rtsp 送到海康录像机能正常显示 通过 intel 的 qsv 硬件编码的 h264/h265 等送到海康录像机只能显示出关键帧,其他 P 帧无法显示(没有 B 帧),通过英伟达显卡硬件编码的 h264/h265 送到海康能正常显示。 以上所有编码后的数据都是通过 rtsp 服务推送的,所有的在 vlc 等播放器上都能正显示。 目前大部分都是核显,所以想解决 qsv 硬件编码问题 下面是部分初始化代码,有偿协助

     // 查找编码器(支持硬件编码) video_codec_ = FindBestEncoder(config_.use_hardware_encoding); // 检查是否使用了硬件编码器 video_using_hardware_ = (strcmp(video_codec_->name, "libx264") != 0 && strcmp(video_codec_->name, "libx265") != 0); // 创建编码器上下文 video_codec_ctx_ = avcodec_alloc_context3(video_codec_); // 设置编码参数 video_codec_ctx_->width = config_.width; video_codec_ctx_->height = config_.height; video_codec_ctx_->time_base.num = 1; video_codec_ctx_->time_base.den = config_.fps; video_codec_ctx_->framerate.num = config_.fps; video_codec_ctx_->framerate.den = 1; video_codec_ctx_->bit_rate = config_.bitrate; video_codec_ctx_->gop_size = config_.fps * 3; // 每 3 秒一个关键帧 video_codec_ctx_->has_b_frames = 0; video_codec_ctx_->max_b_frames = 0; video_codec_ctx_->refs = 1; // 根据编码器类型设置像素格式 if (video_using_hardware_) { // 硬件编码器使用 NV12 格式( QSV 、NVENC 、AMF 都支持) video_codec_ctx_->pix_fmt = AV_PIX_FMT_NV12; } else { // 软件编码器使用 YUV420P video_codec_ctx_->pix_fmt = AV_PIX_FMT_YUV420P; } video_codec_ctx_->flags = AV_CODEC_FLAG_LOW_DELAY | AV_CODEC_FLAG_GLOBAL_HEADER; video_codec_ctx_->rc_buffer_size = config_.bitrate; // 缓冲区大小等于码率 video_codec_ctx_->rc_max_rate = config_.bitrate; // 最大码率 video_codec_ctx_->rc_min_rate = config_.bitrate/5; // 最小码率 if (!video_using_hardware_) { // 软件编码器特定参数 video_codec_ctx_->thread_count = 4; if (strcmp(video_codec_->name, "libx264") == 0) { // libx264 特定选项 if (!config_.preset.isEmpty()) { av_opt_set(video_codec_ctx_->priv_data, "preset", config_.preset.toStdString().c_str(), 0); } if (!config_.tune.isEmpty()) { av_opt_set(video_codec_ctx_->priv_data, "tune", config_.tune.toStdString().c_str(), 0); } if (!config_.profile.isEmpty()) { av_opt_set(video_codec_ctx_->priv_data, "profile", config_.profile.toStdString().c_str(), 0); } av_opt_set(video_codec_ctx_->priv_data, "x264opts", "bframes=0:rc-lookahead=0:scenecut=0", 0); } else if (strcmp(video_codec_->name, "libx265") == 0) { // libx265 特定选项 if (!config_.preset.isEmpty()) { av_opt_set(video_codec_ctx_->priv_data, "preset", config_.preset.toStdString().c_str(), 0); } if (!config_.tune.isEmpty()) { av_opt_set(video_codec_ctx_->priv_data, "tune", config_.tune.toStdString().c_str(), 0); } // H.265 的 profile: main, main10, main-intra 等 if (!config_.profile.isEmpty()) { QString profile_to_use = config_.profile; // 检查 profile 是否与 H.265 兼容 // H.264 的 profile (baseline, high) 不能用于 H.265 if (profile_to_use == "baseline" || profile_to_use == "high") { profile_to_use = "main"; // H.265 的默认 profile LOG(WARNING) << "H.265 不支持 profile \"" << config_.profile.toStdString() << "\", 已自动调整为 \"main\""; } av_opt_set(video_codec_ctx_->priv_data, "profile", profile_to_use.toStdString().c_str(), 0); } // H.265 低延迟参数 av_opt_set(video_codec_ctx_->priv_data, "x265-params", "bframes=0:rc-lookahead=0:scenecut=0:aq-mode=0", 0); } } else { // 硬件编码器特定参数 const char* codec_name = video_codec_->name; if (strcmp(codec_name, "h264_qsv") == 0 || strcmp(codec_name, "hevc_qsv") == 0) { // Intel QSV 编码器参数 // QSV 的 preset 值: veryfast, faster, fast, medium, slow, slower, veryslow av_opt_set(video_codec_ctx_->priv_data, "preset", "veryfast", 0); av_opt_set(video_codec_ctx_->priv_data, "async_depth", "1", 0); // 低延迟 av_opt_set(video_codec_ctx_->priv_data, "look_ahead", "0", 0); // 关闭前瞻 // H.264 专用:添加严格的兼容性参数以解决海康录像机播放问题 if (strcmp(codec_name, "h264_qsv") == 0) { // 强制使用 baseline profile (如果配置中指定了) if (!config_.profile.isEmpty()) { av_opt_set(video_codec_ctx_->priv_data, "profile", config_.profile.toStdString().c_str(), 0); } // 强制 CAVLC 熵编码( baseline profile 必需,H.264 标准) // QSV 默认可能使用 CABAC ,这会导致不兼容 baseline profile av_opt_set(video_codec_ctx_->priv_data, "cavlc", "1", 0); // 设置 H.264 level ( 40 = level 4.0 ,支持 1080p@30fps ) // 与 NVENC 保持一致,提高兼容性 av_opt_set(video_codec_ctx_->priv_data, "level", "40", 0); // 禁用 B 帧策略(确保真正不使用 B 帧) av_opt_set(video_codec_ctx_->priv_data, "b_strategy", "0", 0); // 禁用自适应 I 帧和 B 帧(提高 GOP 结构的一致性) av_opt_set(video_codec_ctx_->priv_data, "adaptive_i", "0", 0); av_opt_set(video_codec_ctx_->priv_data, "adaptive_b", "0", 0); // 严格的 GOP 结构(不允许动态调整关键帧位置) av_opt_set(video_codec_ctx_->priv_data, "strict_gop", "1", 0); // 低延迟模式(类似 NVENC 的 zerolatency ) av_opt_set(video_codec_ctx_->priv_data, "low_delay_brc", "1", 0); LOG(INFO) << "Intel QSV H.264 编码器:已启用海康录像机兼容模式( baseline+CAVLC+level4.0 )"; } } else if (strcmp(codec_name, "h264_nvenc") == 0 || strcmp(codec_name, "hevc_nvenc") == 0) { // NVIDIA NVENC 编码器参数 // NVENC 的 preset: default, slow, medium, fast, hp, hq, bd, ll, llhq, llhp, lossless, losslesshp av_opt_set(video_codec_ctx_->priv_data, "preset", "llhp", 0); // 低延迟高性能 av_opt_set(video_codec_ctx_->priv_data, "zerolatency", "1", 0); av_opt_set(video_codec_ctx_->priv_data, "delay", "0", 0); } else if (strcmp(codec_name, "h264_amf") == 0 || strcmp(codec_name, "hevc_amf") == 0) { // AMD AMF 编码器参数 av_opt_set(video_codec_ctx_->priv_data, "usage", "lowlatency", 0); av_opt_set(video_codec_ctx_->priv_data, "quality", "speed", 0); } else if (strcmp(codec_name, "h264_mf") == 0) { // Windows Media Foundation 编码器参数 av_opt_set(video_codec_ctx_->priv_data, "rate_control", "cbr", 0); } // NVENC 的 profile 设置( QSV 已在上面单独设置) if (!config_.profile.isEmpty() && strcmp(codec_name, "h264_nvenc") == 0) { // NVENC 支持标准 H.264 profiles: baseline, main, high av_opt_set(video_codec_ctx_->priv_data, "profile", config_.profile.toStdString().c_str(), 0); } } // 初始化硬件加速上下文(如果使用硬件编码) if (!InitializeHardwareContext()) { LOG(ERROR) << "硬件加速上下文初始化失败"; return false; } // 打开编码器 int ret = avcodec_open2(video_codec_ctx_, video_codec_, nullptr); if (ret < 0) { char errbuf[AV_ERROR_MAX_STRING_SIZE]; av_strerror(ret, errbuf, sizeof(errbuf)); LOG(ERROR) << "无法打开编码器: " << errbuf; return false; } 
    2 条回复    2025-12-17 18:06:32 +08:00
    okkk
        1
    okkk  
       3 小时 26 分钟前
    yoyoluck
        2
    yoyoluck  
    OP
       3 小时 22 分钟前
    @okkk 谢谢你的回答,应该不是这几个问题导致的。能播放和不能播放的流数据我都分析过,基本上都一样,目前发现 P 帧中某几个参数不一致。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3017 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 20ms UTC 13:29 PVG 21:29 LAX 05:29 JFK 08:29
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86