【问题标题】:what is 'linesize alignment' meaning?'linesize 对齐'是什么意思?
【发布时间】:2016-06-11 05:20:17
【问题描述】:

我正在关注http://dranger.com/ffmpeg/tutorial01.html中的ffmpeg教程。

我刚刚发现 avpicture_get_size 函数已被弃用。

所以我检查了 ffmpeg 的文档(https://www.ffmpeg.org/doxygen/3.0/group__lavu__picture.html#ga24a67963c3ae0054a2a4bab35930e694) 并找到了替代品av_image_get_buffer_size。

但是我看不懂align参数的意思'linesize alignment'......

什么意思?

【问题讨论】:

  • 可能你可以使用函数 av_image_get_linesize 获得 linesize。我对这个库一无所知,只是在同一页面上为 linesize 做了 ctrl+f。这似乎是某种基于格式/尺寸的内部对齐要求
  • 另外,如果这个问题被社区关闭,我也不会感到惊讶。欢迎来到 SO /s。
  • 感谢@PreetKukreti 的幽默。 :-)
  • PATH_TO_INSTALL_DIR/share/ffmpeg/examples/hw_decode.c: size = av_image_get_buffer_size(tmp_frame->format, tmp_frame->width, tmp_frame->height, 1);

标签: c++ ffmpeg


【解决方案1】:

FFmpeg 的某些部分,尤其是 libavcodec,需要对齐的 linesizes[],这意味着它需要:

assert(linesize[0] % 32 == 0);
assert(linesize[1] % 32 == 0);
assert(linesize[2] % 32 == 0);

这允许它使用快速/对齐的 SIMD 例程(例如 SSE2/AVX2 movdqa 或 vmovdqa 指令)进行数据访问,而不是使用较慢的未对齐对应例程。

这个av_image_get_buffer_size函数的align参数就是这个行对齐,你需要它,因为缓冲区的大小受它的影响。例如,YUV 缓冲区中 Y 平面的大小实际上不是宽度 * 高度,而是 linesize[0] * 高度。您会看到(尤其是对于不是 16 或 32 倍数的图像大小),当您将 align 增加到 2 的更高次方时,返回值会缓慢增加。

实际上,如果您打算将此图片用作调用的输出缓冲区,例如avcodec_decode_video2,应该是32。对于swscale/avfilter,我相信没有绝对要求,但建议还是32。

【讨论】:

  • 为什么只有 32 个?现代 SIMD 例程适用于 128 位甚至 256 位操作。你知道吗?
  • 256 / 8 = 32。它以字节为单位,而不是位。
  • 写得很好,解释得很好!
  • 请注意:如果您需要将对齐数据转换为非对齐数据(例如,将它们输出到原始缓冲区以进行外部处理或输出到文件),请使用av_image_copy(unalignedFrame->data, unalignedFrame->linesize, const_cast<const uint8_t **>(alignedFrame->data), alignedFrame->linesize, pix_fmt, width, height),其中alignedFrame 和@ 987654330@ 是像素格式相同但对齐方式不同的帧。
【解决方案2】:

我的做法:

1.avpicture 已弃用的问题,我将 avpicture 函数替换为 AVFrame 和 imgutils 函数。代码示例:

   //AVPicture           _picture;
   AVFrame             *_pictureFrame;
   uint8_t             *_pictureFrameData;

...

//_pictureValid = avpicture_alloc(&_picture,
//                                AV_PIX_FMT_RGB24,
//                               _videoCodecCtx->width,
//                               _videoCodecCtx->height) == 0;

_pictureFrame = av_frame_alloc();
_pictureFrame->width = _videoCodecCtx->width;
_pictureFrame->height = _videoCodecCtx->height;
_pictureFrame->format = AV_PIX_FMT_RGB24;

int size = av_image_get_buffer_size(_pictureFrame->format,
                                    _pictureFrame->width,
                                    _pictureFrame->height,
                                    1);

//dont forget to free _pictureFrameData at last                                    
_pictureFrameData = (uint8_t*)av_malloc(size);

 av_image_fill_arrays(_pictureFrame->data,
                      _pictureFrame->linesize,
                      _pictureFrameData,
                      _pictureFrame->format,
                      _pictureFrame->width,
                      _pictureFrame->height,
                      1);

...

if (_pictureFrame) {
    av_free(_pictureFrame);
    if (_pictureFrameData) {
        free(_pictureFrameData);
    }
}

2.align参数

首先我将align设置为32,但是对于某些视频流它不起作用,导致图像失真。然后我将它设置为 16(我的环境:mac、Xcode、iPhone6),一些流运行良好。但最后我将align设置为1,因为我找到了this

Fill in the AVPicture fields, always assume a linesize alignment of 1. 

【讨论】:

  • 那么最后如何正确计算所有视频文件的align?
  • 如果 ffmpeg 在某个时间点能清除这个问题会很好:O
【解决方案3】:

如果您查看 3.2 版本中avpicture_get_size 的定义,您会看到以下代码:

int avpicture_get_size(enum AVPixelFormat pix_fmt, int width, int height)
{
    return av_image_get_buffer_size(pix_fmt, width, height, 1);
}

它只是调用建议的函数:av_image_get_buffer_size,并将align 参数设置为1。我没有进一步了解为什么将1 用于折旧功能的全部意义。与 ffmpeg 一样,通过阅读正确的代码和足够的代码(通过一些代码实验)可能会弄清楚。

【讨论】:

    猜你喜欢
    • 2014-09-24
    • 2011-05-09
    • 2023-03-25
    • 2021-08-23
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2012-07-01
    相关资源
    最近更新 更多