f 性能优化-Android Camera Hal中通过Neon指令优化数据拷贝 - Powered by qidao123.com技术社区

Android Camera Hal中通过Neon指令优化数据拷贝

打印 上一主题 下一主题

主题 2012|帖子 2012|积分 6036


配景形貌:
Camera apk普通相机模式录像操作时,一般是同时请求两个流,即预览流和录像流。对于两个流输出图像格式和分辨率雷同的情况下,是不是可以通过一个流拷贝得到另一个流的数据,进而节省掉一个Sensor输出处理两次的的开销?
我们都知道平常使用的memcpy()函数是由cpu来实现处理的,如果图像数据比较大的话是很耗cpu的,那么有没有什么方法能优化下copy操作使cpu占用小些?
这里介绍使用ARM Neon指令集实现输出拷贝的优化。

下面以具体实现,了解如何使用Neon指令实现一帧NV12图像数据的拷贝。
Android源码中有对Neon的支持,只必要在使用的模块引用&调用就可以了,实现如下:
  1. #include <arm_neon.h>   //neon指令相关数据结构和接口定义
  2. void NeonMemcpy(void *dest, const void *src, size_t size)
  3. {
  4.      uint8_t* dst8 = static_cast<uint8_t*>(dest);
  5.      const uint8_t* src8 = static_cast<const uint8_t*>(src);
  6.      //小数据直接拷贝
  7.      if (size < 64) {
  8.          for (; size > 0; size--) {
  9.              *dst8++ = *src8++;
  10.          }
  11.          return;
  12.      }
  13.      // 64字节对齐预处理
  14.      const uintptr_t mask = 0x3F;
  15.      const uintptr_t misalign = reinterpret_cast<uintptr_t>(src8) & mask;
  16.      if (misalign > 0) {
  17.          const size_t align_bytes = 64 - misalign;
  18.          for (size_t i = 0; i < align_bytes; i++) {
  19.              *dst8++ = *src8++;
  20.          }
  21.          size -= align_bytes;
  22.      }
  23.      // 主拷贝循环(每次64字节)
  24.      const size_t chunks = size >> 6; // 64字节块数
  25.      for (size_t i = 0; i < chunks; i++) {
  26.          // 使用基本NEON指令替代vld1q_u8_x4
  27.          uint8x16_t data0 = vld1q_u8(src8);        //从src8加载16个8位数据到data0
  28.          uint8x16_t data1 = vld1q_u8(src8 + 16);
  29.          uint8x16_t data2 = vld1q_u8(src8 + 32);
  30.          uint8x16_t data3 = vld1q_u8(src8 + 48);
  31.          vst1q_u8(dst8, data0);                   //将data0中的16个8位数据存储到dst8中
  32.          vst1q_u8(dst8 + 16, data1);
  33.          vst1q_u8(dst8 + 32, data2);
  34.          vst1q_u8(dst8 + 48, data3);
  35.          src8 += 64;
  36.         dst8 += 64;
  37.     }
  38.     // 处理剩余数据(16字节块)
  39.     size &= 63;
  40.     const size_t vec16_count = size >> 4;
  41.     for (size_t i = 0; i < vec16_count; i++) {
  42.         vst1q_u8(dst8, vld1q_u8(src8));
  43.         src8 += 16;
  44.         dst8 += 16;
  45.         size -= 16;
  46.     }
  47.     // 尾部字节处理
  48.     for (; size > 0; size--) {
  49.         *dst8++ = *src8++;
  50.     }
  51. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

温锦文欧普厨电及净水器总代理

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表