c++ - 如何使用模式从内存中复制字节(YUYV 打包到 YUV420 平面)

标签 c++ memory-management video-processing micro-optimization pixelformat

让我们从这里开始:

我有一个 16 字节的内存块,我只需要将偶数字节复制到一个 8 字节的内存块。

我目前的算法是这样的:

unsigned int source_size = 16, destination_size = 8, i;

unsigned char * source = new unsigned char[source_size];
unsigned char * destination = new unsigned char[destination_size];

// fill source
for( i = 0; i < source_size; ++i)
{
    source[i] = 0xf + i;
}
// source :
// 0f 10 11 12  13 14 15 16  17 18 19 1a  1b 1c 1d 1e

// copy
for( i = 0; i < destination_size; ++i)
{
    destination[i] = source[i * 2];
}
// destination :
// 0f 11 13 15  17 19 1b 1d

这只是一个示例,因为我想知道当我需要获取每第 3 个字节或每第 4 个字节时是否有更好的方法来执行此操作,而不仅仅是偶数个字节。

我知道使用循环我可以实现这个但我需要优化这个...我不完全知道如何使用 SSE 所以我不知道在这种情况下是否可以使用,但是像 memcpy magic有点事情会很棒。

我还考虑过使用宏来摆脱循环,因为源和目标的大小都是恒定的,但这看起来没什么大不了的。

如果我说这是提取 YUYV 像素格式的 YCbCr 字节,您可能会跳出框框。另外我需要强调的是,我这样做是为了摆脱 libswscale。

最佳答案

虽然我怀疑编译器和 cpu 在这种情况下已经做得很好;如果您真的想要替代方案,请研究一下反转莫顿数的技术。这个问题How to de-interleave bits (UnMortonizing?)展示了如何在位上执行此操作,但这个想法也可以扩展到字节。

类似的东西(仅作为示例,这不是生产质量)

// assuming destination is already zero...
For (int i=0; i < destination_size; i += 2) {
   long* pS = (long*) &source[ i * 2 ];
   long* pD = (long*) &destination[ i ];
   long a = *pS &0xff00ff00;
   *pD |= *pS | ( *pS << 8 );
}

这是否比您的版本快取决于确切的 cpu 类型和编译器生成的内容。即测试并查看哪个更快,正如其他人所提到的,内存获取瓶颈将掩盖给定小数组的所有内容。

关于c++ - 如何使用模式从内存中复制字节(YUYV 打包到 YUV420 平面),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30236544/

相关文章:

C++ - 使用 std::vector 和相关内存管理的正确方法

android - MediaMuxer 视频文件大小减小(重新压缩,降低分辨率)

video - 如何压缩具有均匀模糊的视频是压缩的唯一副作用?

video - 为什么ffmpeg-split AVI电影在播放时会卡住

c++ - 在 C++ 控制台应用程序中编写 sql 查询?

c++ - 从 C++ 调用 WDF 驱动程序

C++ 枚举问题和 g++ 中可能的循环依赖

C++ 堆栈使用模板化链表 - 内存泄漏

c++ - 简单继承获取 Vtable 错误

c++ - C++中的内存异常