1

SDL_Overlay在使用(SDL 1.2.5)播放某些未压缩的 YUV 4:2:0 平面视频数据源时,我一直在与一个问题作斗争。

我播放640x480视频没有问题。但我刚刚尝试播放分辨率为854x480的视频,我得到了一个奇怪的效果。这条线太迟包裹 1-2 个像素(导致类似剪切的变换),色度消失,每条线上都用交替的 R、G 或 B 代替。看这个截图

YUV 数据本身是正确的,因为我可以将其保存到文件并在另一个播放器中播放。此时未填充 -间距与行长匹配。

我怀疑当分辨率不是 4 的倍数时会出现一些问题。也许SDL_Surface期望SDL_Overlay色度分辨率是 2 的倍数?

更令我怀疑的是,我注意到我以854*480SDL_Surface大小创建的 RGB的间距为2564,而不是我期望的3*854 = 2562 。

如果我在宽度上添加 1 或 2 个像素SDL_Surface(但保持叠加层和矩形相同),它可以正常工作,尽管右侧有黑色边框。当然,这会与四的倍数的视频中断

设置

screen = SDL_SetVideoMode(width, height, 24, SDL_SWSURFACE|SDL_ANYFORMAT|SDL_ASYNCBLIT);
if ( screen == NULL ) {
  return 0;
}
YUVOverlay = SDL_CreateYUVOverlay(width, height, SDL_IYUV_OVERLAY, screen);
Ydata = new unsigned char[luma_size];
Udata = new unsigned char[chroma_size];
Vdata = new unsigned char[chroma_size];

YUVOverlay->pixels[0] = Ydata;
YUVOverlay->pixels[1] = Udata;
YUVOverlay->pixels[2] = Vdata;

SDL_DisplayYUVOverlay(YUVOverlay, dest);

渲染循环:

SDL_LockYUVOverlay(YUVOverlay);
memcpy(Ydata, buffer, luma_size);
memcpy(Udata, buffer+luma_size, chroma_size);
memcpy(Vdata, buffer+luma_size+chroma_size, chroma_size);
int i = SDL_DisplayYUVOverlay(YUVOverlay, dest);
SDL_UnlockYUVOverlay(YUVOverlay);

对我来说最简单的解决方法是增加 RGBSDL_Surface大小,使其在每个维度上都是 4 的倍数。但这会增加一个黑色边框。

有没有解决这个问题的正确方法?我应该尝试在我的 YUV 数据上使用填充吗?

4

1 回答 1

1

输入数据的每个平面必须从可被 8 整除的地址开始,并且每行的步幅必须能被 8 整除。要清楚:您的色度平面也需要遵守这一点。

这个要求似乎来自 SDL 库在 x86 cpu 上使用 MMX 多媒体指令。请参阅发行版中 src/video/SDL_yuv_mmx.c 中的注释。

更新:我查看了实际的汇编代码,还有源代码注释中没有提到的附加假设。这适用于 SDL 1.2.14。除了上面描述的模 8 假设之外,代码还假设输入亮度和输入色度平面都被完美地打包(即宽度 == 步幅)。

于 2013-03-23T16:41:58.630 回答