视频播放:内存对齐导致的width不等于linesize和解决

拿到视频的帧数据后,可能width并不等于linesize,直接使用width来生成纹理会导致扭曲。

width是视频的宽度,这个是实际的,linesize是一行数据的字节数量。图像是2维的,但数据存储确实1维的,即uint8_t*,而不是用二维数组来存储,不是每行数据单独一个指针。

所以就需要知道一行的数据大小,这样才能确定每一行的数据开头在哪。比如数据是:12345678,每行两个,那第二行就是34,如果每行3个,那么就是456。

对于YUV420p,3个分量是分层的,但看Y,每个像素的1个字节,如果宽度为100,那么一行就有100个Y,那么linesize就是100。也就是说一般情况下,Y这个层的linesize就等于width,那么为什么会可能会不等于呢?应该是因为编码的时候使用内存对齐导致的。比如视频宽度232,然后使用24作为对齐的基本单位,那么linesize就会变成240,会多出8个字节。

如果直接使用width作为linesize,为什么会导致扭曲?

假设正确数据是:

1234567x
1234567x
1234567x

x是对齐多出来的无用数据,使用linesize为8就是正常显示,然后width是7,使用7就会变成:

1234567
x123456
7x12345

单看1或者2,就会发现变成倾斜的了,实际看起来视频就是这样充满了右斜的线。

怎么解决?

可以对视频帧数据进行重采样,把多余的数据删掉,比如上面,把数据变成1234567 1234567 1234567,使用linesize为7也是正确的。

只是这样貌似消耗太大,要进行大量的内存拷贝。

如果只是把linesize从width改为正确的值,视频不扭曲了,但是在右边会出现因为无用数据导致的空白区(我测试在iOS上显示绿色)。

怎么去除这个空白区?

想象一下视频裁剪,假如我们可以裁剪,那么直接把右侧那部分裁掉不就好了。

参考这篇文章texture对齐和裁剪,使用glPixelStorei(GL_UNPACK_ROW_LENGTH, linesize[0]);
可以让纹理读取数据的时候按照设定的大小读取,这个值概念上跟linesize是一样的,这样就不会把无效的数据读取进去了。

你可能感兴趣的:(视频播放:内存对齐导致的width不等于linesize和解决)