背景描述:
Camera apk普通相机模式录像操作时,一般是同时请求两个流,即预览流和录像流。对于两个流输出图像格式和分辨率相同的情况下,是不是可以通过一个流拷贝得到另一个流的数据,进而节省掉一个Sensor输出处理两次的的开销?
我们都知道平时使用的memcpy()函数是由cpu来实现处理的,如果图像数据比较大的话是很耗cpu的,那么有没有什么方法能优化下copy操作使cpu占用小些?
这里介绍使用ARM Neon指令集实现输出拷贝的优化。
下面以具体实现,了解如何使用Neon指令实现一帧NV12图像数据的拷贝。
Android源码中有对Neon的支持,只需要在使用的模块引用&调用就可以了,实现如下:
#include <arm_neon.h> //neon指令相关数据结构和接口定义void NeonMemcpy(void *dest, const void *src, size_t size){uint8_t* dst8 = static_cast<uint8_t*>(dest);const uint8_t* src8 = static_cast<const uint8_t*>(src);//小数据直接拷贝if (size < 64) {for (; size > 0; size--) {*dst8++ = *src8++;}return;}// 64字节对齐预处理const uintptr_t mask = 0x3F;const uintptr_t misalign = reinterpret_cast<uintptr_t>(src8) & mask;if (misalign > 0) {const size_t align_bytes = 64 - misalign;for (size_t i = 0; i < align_bytes; i++) {*dst8++ = *src8++;}size -= align_bytes;}// 主拷贝循环(每次64字节)const size_t chunks = size >> 6; // 64字节块数for (size_t i = 0; i < chunks; i++) {// 使用基本NEON指令替代vld1q_u8_x4uint8x16_t data0 = vld1q_u8(src8); //从src8加载16个8位数据到data0uint8x16_t data1 = vld1q_u8(src8 + 16);uint8x16_t data2 = vld1q_u8(src8 + 32);uint8x16_t data3 = vld1q_u8(src8 + 48);vst1q_u8(dst8, data0); //将data0中的16个8位数据存储到dst8中vst1q_u8(dst8 + 16, data1);vst1q_u8(dst8 + 32, data2);vst1q_u8(dst8 + 48, data3);src8 += 64;dst8 += 64;}// 处理剩余数据(16字节块)size &= 63;const size_t vec16_count = size >> 4;for (size_t i = 0; i < vec16_count; i++) {vst1q_u8(dst8, vld1q_u8(src8));src8 += 16;dst8 += 16;size -= 16;}// 尾部字节处理for (; size > 0; size--) {*dst8++ = *src8++;}
}