我有一个输入图像A和一个以YUV420格式存储的大小为800x600的结果图像B,我需要将图像A缩放为100x100的大小,并在某个点(x = 100,y = 100)将其放置到结果图像B中。为了减少内存和CPU使用率,我将swscale结果直接放入了最终的B图像。

这是一个代码片段(非常简单):

//here we a creating sws context for scaling into 100x100
sws_ctx = sws_getCachedContext(sws_ctx, frame.hdr.width, frame.hdr.height, AV_PIX_FMT_YUV420P,
                               100, 100, AV_PIX_FMT_YUV420P, SWS_BILINEAR, nullptr, nullptr, nullptr);

接下来,我们创建相应的 slice 并大步描述图像A
    int src_y_plane_sz = frame.hdr.width * frame.hdr.height;
    int src_uv_plane_sz = src_y_plane_sz / 2;
    std::int32_t src_stride[] = {
        frame.hdr.width,
        frame.hdr.width / 2,
        frame.hdr.width / 2,
        0};

    const uint8_t* const src_slice[] = {
        &frame.raw_frame[0],
        &frame.raw_frame[0] + src_y_plane_sz,
        &frame.raw_frame[0] + src_y_plane_sz + src_uv_plane_sz,
        nullptr};

现在对目标B图像执行相同操作
    std::int32_t dst_stride[] = {
        current_frame.hdr.width,
        current_frame.hdr.width /2,
        current_frame.hdr.width /2,
        0
    };

    std::int32_t y_plane_sz = current_frame.hdr.width * current_frame.hdr.height;
    std::int32_t uv_plane_sz = y_plane_sz / 2;

    //calculate offset in slices for x=100, y=100 position
    std::int32_t y_offset = current_frame.hdr.width * 100 + 100;

    uint8_t* const dst_slice[] = {
        &current_frame.raw_frame[0] + y_offset,
        &current_frame.raw_frame[0] + y_plane_sz + y_offset / 2,
        &current_frame.raw_frame[0] + y_plane_sz + uv_plane_sz + y_offset / 2,
        nullptr};

毕竟-调用swscale
    int ret = sws_scale(sws_ctx, src_slice, src_stride, 0, frame.hdr.height,
                        dst_slice, dst_stride);

使用测试序列后,我得到一些无效结果,并存在以下问题:
  • Y组件有一些填充线
  • UV组件放错了位置-
    它们比原始的Y分量要低一些。

  • c++ - 使用swscale进行图像合成-LMLPHP

    有没有人在swscale函数上有同样的问题?我对这个FFmpeg库集合还很陌生,所以我对如何正确执行此任务持任何意见。

    FFmpeg版本使用3.3

    最佳答案

    YUV420格式将图像的宽度和高度都缩放两倍。即每个色平面比亮度平面小4倍:

    int src_uv_plane_sz = src_y_plane_sz / 4;
    

    我也不确定计算的步幅值是否正确。通常跨度!=宽度。

    10-07 19:24
    查看更多