【问题标题】:Data loss while converting from jpeg to BGRA using ffmpeg使用 ffmpeg 从 jpeg 转换为 BGRA 时数据丢失
【发布时间】:2015-04-21 21:41:34
【问题描述】:

我正在尝试使用 ffmpeg 将 JPG 帧转换为 RGBA 帧。原始图像大小为 250x250,像素格式为 AV_PIX_FMT_YUV420P。源线步幅数组包含 [256, 128, 128](用于 3 个平面)。我的目标帧大小是 250x250。以下是代码。

AVFrame* GetBGRAFrame(AVFrame* pFrame)
{       
    const int kiImageWidth = pFrame->width ;
    const int kiImageHeight = pFrame->height ;

    int iDestWidth = kiImageWidth;
    int iDestHeight = kiImageHeight;

    AVPixelFormat enPixelFormat = (AVPixelFormat)pFrame->format ;

    SwsContext* pImageConvertContext =
        sws_getContext(kiImageWidth, kiImageHeight, enPixelFormat, 
        iDestWidth, iDestHeight, PIX_FMT_BGRA, 0, NULL, NULL, NULL);

    // Allocate destination frame
    int iNumBytes = avpicture_get_size(AV_PIX_FMT_BGRA, iDestWidth, iDestHeight);
    AVFrame* pFrame2 = av_frame_alloc();
    uint8_t* pFrameBuffer = (uint8_t*)av_malloc(iNumBytes * sizeof(uint8_t));       
    avpicture_fill((AVPicture*)pFrame2, pFrameBuffer, AV_PIX_FMT_BGRA, iDestWidth, iDestHeight);

    sws_scale(pImageConvertContext, pFrame->data, pFrame->linesize, 0, kiImageHeight, pFrame2->data, pFrame2->linesize);
    sws_freeContext(pImageConvertContext);

    return pFrame2;
}

转换后,我的目标框架右侧有 2 个透明列。

如果我使用命令行工具,我可以获得正确的图像: ffmpeg -i image.jpg 输出.png

那么,我的代码有什么问题?

目的地有对齐要求吗?如果是,我应该如何更改我的代码以获得 250x250 BGRA 帧?

谢谢

【问题讨论】:

  • 什么版本的 FFmpeg(或 libswscale)?
  • 尝试将SWS_POINT 而不是0 传递到sws_getContext
  • @Mark:我尝试过 SWS_POINT、SWS_AREA、SWS_BILINEAR、SWS_BICUBIC 和 SWS_LANCZOS。问题仍然存在。

标签: image-processing ffmpeg


【解决方案1】:

我认为您在 yuv420p 到 RGB24 的转换中遇到了 this 代码:

h_size = (c->dstW + 7) & ~7;                                     \
if (h_size * depth > FFABS(dstStride[0]))                        \
    h_size -= 8;                                                 \

由于 avpicture_get_size() 应该为您处理所有这些,我想说这是一个错误,您应该在 trac.ffmpeg.org 或邮件列表上报告...

[编辑] 作为一种实用的解决方法,请关注linked bug report 的此评论:

改为直接调用 av_image_alloc() [..],对齐参数为 32。

【讨论】:

  • 我发现,这是FFmpeg中的一个错误。 trac.ffmpeg.org/ticket/1031#comment:7 一种解决方法是使用 --disable-asm 关闭 asm 代码。
  • 更好的解决方法是遵循以下评论:“直接调用 av_image_alloc() [..],对齐参数为 32。”
  • 我可以通过将目标缓冲区显式对齐为 8 的倍数来修复它。 av_image_alloc 似乎也在工作。我想我会选择 av_image_alloc。谢谢罗纳德。
猜你喜欢
  • 2022-12-25
  • 1970-01-01
  • 1970-01-01
  • 2014-07-13
  • 1970-01-01
  • 2017-08-09
  • 1970-01-01
  • 2019-12-05
  • 1970-01-01
相关资源
最近更新 更多