“linesize对齐”是什么意思?

25

1
可能可以使用函数av_image_get_linesize获取行大小。我对这个库一无所知,只是在同一页上使用了ctrl+f查找linesize。它似乎是基于格式/尺寸的某种内部对齐要求。 - Preet Kukreti
1
此外,如果这个问题被社区关闭,我也不会感到惊讶。欢迎来到SO /s。 - Preet Kukreti
谢谢你的幽默感@PreetKukreti. :-) - aggieNick02
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); - megorit
3个回答

29

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平面的大小实际上不是width * height,而是linesize [0] * height。您会发现(特别是对于不是16或32的倍数的图像大小),随着将align增加到2的更高次幂,返回值会慢慢增加。

实际上,如果您要将此图像用作对e.g. avcodec_decode_video2 的调用的输出缓冲区,则应设置为32。对于swscale / avfilter,我认为没有绝对要求,但建议仍将其设置为32。


为什么只有32位?现代SIMD例程是为128位甚至256位操作而设计的。你对此了解吗? - Georg Schölly
1
256 / 8 = 32。这是字节,不是位。 - Ronald S. Bultje
写得非常好,解释得也很清楚! - rkosegi
请注意:如果您需要将对齐的数据转换为非对齐的(例如将它们输出到原始缓冲区进行外部处理或输出到文件中),请使用 av_image_copy(unalignedFrame->data, unalignedFrame->linesize, const_cast<const uint8_t **>(alignedFrame->data), alignedFrame->linesize, pix_fmt, width, height),其中 alignedFrameunalignedFrame 是具有相同像素格式但不同对齐方式的帧。 - Martin Pecka

11

我的做法:

1.avpicture 已经被弃用,我将 avpicture 函数替换为 AVFrameimgutils 函数。代码示例:

   //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设置为32,但是对于某些视频流它并不起作用,导致图像失真。然后我将其设置为16我的环境:mac、Xcode、iPhone6),某些流能够正常工作。但最终我将align设置为1,因为我发现了这个

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

2
那么最终如何正确计算所有视频文件的“对齐”? - CAMOBAP
1
希望FFmpeg在某个时候能够清理掉这个问题:O - Andrea Catania

5
如果您查看版本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_sizealign参数设置为1。我没有进一步了解为什么弃用的函数使用1的全部意义。通常情况下,对于ffmpeg,可以通过阅读正确的代码和足够的代码(以及一些代码实验)来理解它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接