背景描述:
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++;}
}