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

标签 c++ c ffmpeg video-processing swscale

我有一个输入图像 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);

接下来我们创建描述图像 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);

使用测试序列后,我得到了一些无效结果,并存在以下问题:

  1. Y 组件有一些填充线
  2. UV 组件放错位置 - 它们比原始 Y 分量要低一些。

Artefacts

有人在使用 swscale 函数时遇到过同样的问题吗?我对这个 FFmpeg 库集合还很陌生,所以我愿意接受任何关于如何正确执行此任务的意见。

使用的FFmpeg版本为3.3

最佳答案

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

int src_uv_plane_sz = src_y_plane_sz / 4;

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

关于c++ - 使用 swscale 进行图像合成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51800507/

相关文章:

c++ - cppcheck: header 中的函数定义

c - 取消引用结构体的双指针时出现问题

opencv - 错误交叉编译 : hidden symbol . .. 最终链接失败

c++ - OpenCV - 具有 filter2D 和双值的 gaussianKernel

c++ - 如何从成员 QThread 更改 QMainWindow 上的 Qt GUI 小部件?

c - bluez 中 GATT 服务的回调方法是什么样的?

ffmpeg - 来自 .3gp 文件的缩略图

python - 使用 subprocess.call() 将参数传递给 FFMPEG

c++ - WinAPI EM_STREAMOUT 崩溃

c - C 代码中的内存问题或 Arduino 限制?