发送到编码器的帧的所有平面都与线条大小对齐,线条大小是32(或更大)的倍数。对于格式YUV420P,色度平面的宽度是亮度分量的一半。因此,对于1440的帧宽,色度宽度为720,并且720%32!= 0.但是U和V缓冲区已被指定为宽度x高度的朴素大小。所以当 memcpy 是第一个进行的 (width/2 - (width/2) % 32) 将下一行的元素复制到发送到编码器的帧的步幅填充元素中。这将产生如Q图像中所见的视觉失真。
memcpy
(width/2 - (width/2) % 32)
校正是将原始色度平面缓冲区填充到跨步对齐的大小。 OP的修改与评论相关联
void fill_yuv_imageY(unsigned char **pict, int frame_index, int width, int height) { int x, y, i; i = frame_index; for (y = 0; y < height; y++) for (x = 0; x < width; x++) pict[0][y * width + x] = x + y + i * 3; } void fill_yuv_imageUV(unsigned char **pict, int frame_index, int halfWidth, int height) { int x, y, i; for (y = 0; y < height / 2; y++) { for (x = 0; x < halfWidth; x++) { pict[1][y * halfWidth + x] = 128 + y + i * 2; pict[2][y * halfWidth + x] = 64 + x + i * 5; } } } int roundUp(int numToRound, int multiple){ if (multiple == 0) return numToRound; int remainder = numToRound % multiple; if (remainder == 0) return numToRound; return numToRound + multiple - remainder; } //Allocating test frames unsigned char*** frames = new unsigned char**[frameCount]; for (int i = 0; i < frameCount; i++) { frames[i] = new unsigned char*[3]; frames[i][0] = new unsigned char[width * height]; fill_yuv_imageY(frames[i], i, width, height); frames[i][1] = new unsigned char[roundUp(width / 2, 32) * (height / 2)]; frames[i][2] = new unsigned char[roundUp(width / 2, 32) * (height / 2)]; fill_yuv_imageUV(frames[i], i, roundUp(width / 2, 32), height); }