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

使用swscale将1080p视频下采样至480p并编码为x265时画面异常

解决FFmpeg缩放后x265编码画面异常问题

问题复盘

  • 处理流程:先将1920×1080输入帧通过SWS_BICUBIC算法缩放到854×480,再送入x265编码器
  • 异常表现:
    • 编码器设为1080p时,输出仍为1080p且画面故障
    • 编码器改为854×480时,画面仅显示原帧顶部1/4区域

核心原因分析

新手常踩的三个坑:

  1. 缩放帧缓冲区未正确初始化:sws_scale_frame需要目标帧已按目标分辨率、像素格式分配好独立缓冲区,直接复用输入帧缓冲区会导致数据写入越界或不完整
  2. 编码器参数与缩放帧不匹配:编码器上下文的width/height/pix_fmt必须和缩放后的帧完全一致,否则编码器会按自身参数解析帧数据,导致画面错位
  3. 时间戳未做时间基转换:输入帧的时间基来自解码器,必须转换为编码器的时间基,否则可能引发编码逻辑异常

修复步骤

1. 正确初始化缩放帧缓冲区

在缩放前,确保scaled_frame已按目标参数分配缓冲区:

if (!scaled_frame->buf[0]) {
    scaled_frame->width = 854;
    scaled_frame->height = 480;
    scaled_frame->format = encoder->codec_ctx->pix_fmt; // 必须和编码器格式一致
    if (av_frame_get_buffer(scaled_frame, 0) < 0) {
        fprintf(stderr, "Failed to allocate scaled frame buffer\n");
        return -1;
    }
}

2. 同步编码器与缩放帧参数

初始化编码器前,强制设置与缩放目标一致的参数:

// 编码器上下文配置
encoder->codec_ctx->width = 854;
encoder->codec_ctx->height = 480;
encoder->codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P; // x265推荐格式,避免用RGB
encoder->codec_ctx->time_base = av_make_q(1, 60); // 匹配测试视频60fps帧率

3. 正确创建缩放上下文

确保SWS上下文的源/目标参数完全对应:

encoder->sws_ctx = sws_getContext(
    1920, 1080, decoder->codec_ctx->pix_fmt, // 源分辨率、格式
    854, 480, encoder->codec_ctx->pix_fmt,   // 目标分辨率、格式
    SWS_BICUBIC, NULL, NULL, NULL
);
if (!encoder->sws_ctx) {
    fprintf(stderr, "Failed to create SWS context\n");
    return -1;
}

4. 修正时间戳转换

将输入帧的时间戳转换为编码器的时间基,避免编码异常:

scaled_frame->pts = av_rescale_q(input_frame->pts, decoder->codec_ctx->time_base, encoder->codec_ctx->time_base);
scaled_frame->pkt_dts = av_rescale_q(input_frame->pkt_dts, decoder->codec_ctx->time_base, encoder->codec_ctx->time_base);

调整后的核心代码

// 确保缩放帧缓冲区已正确分配
if (!scaled_frame->buf[0]) {
    scaled_frame->width = 854;
    scaled_frame->height = 480;
    scaled_frame->format = encoder->codec_ctx->pix_fmt;
    if (av_frame_get_buffer(scaled_frame, 0) < 0) {
        fprintf(stderr, "Failed to allocate scaled frame buffer\n");
        return -1;
    }
}

// 转换时间戳并复制帧属性
scaled_frame->pts = av_rescale_q(input_frame->pts, decoder->codec_ctx->time_base, encoder->codec_ctx->time_base);
scaled_frame->pkt_dts = av_rescale_q(input_frame->pkt_dts, decoder->codec_ctx->time_base, encoder->codec_ctx->time_base);
scaled_frame->pict_type = input_frame->pict_type;

// 执行缩放
sws_scale_frame(encoder->sws_ctx, scaled_frame, input_frame);

// 编码
if (encode_video(decoder, encoder, scaled_frame))
    return -1;

额外注意事项

  • 不要直接复用输入帧的缓冲区,必须为缩放帧分配独立内存
  • x265仅支持特定像素格式(如YUV420P),避免使用RGB格式作为输入
  • 测试时确保编码器初始化完成后再开始缩放编码流程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 17:27:41