IPP简介、移植文档 --- 移植入Android
目录
1.1 基本数据类型
1.2 domain
1.3 核心函数
1.4 函数的命名和参数
2.1.1 内存分配函数
2.1.2 vector初始化函数
2.1.3 数值运算类函数
2.2 Image and video processing
2.2.1 内存分配函数
2.2.2 image数据的交换与初始化
2.2.3 图像的数据运算函数
2.2.4 图像颜色转换
2.2.5 图像线性变换
2.2.6 图像压缩
2.2.7 视频编码
2.3 Small martices and realistic rendering
2.3.1 ippm的操作对象
2.3.2 实用函数
2.3.3 矩阵代数运算
2.3.4 线性系统函数
2.3.5 最小平方问题
2.3.6 特征值问题
2.3.7 多维向量的数学操作
2.4 Cryptography
2.4.1 支持的对称加密类型
2.4.2 单路Hash原始加密
2.4.3 公钥加密函数
2.4.3.1 大数运算
2.4.3.2 RSA算法
2.4.3.3 基于离散对象的加密
3.1 IntelIPP库的下载及安装
4.1 在camera中的应用
l 什么是IPP (Intel Integrated Performance Primitives)
IPP“Intel Integrated Performance Primitives” ( Intel IPP )是一套跨平台的软件函数库,他提供了广泛的多媒体功能:音频解码器(例如: H263 、 MPEG-4 )、图像处理 (JPEG) 、信号处理、语音压缩(例如: G723 、 GSM 、 AMR )和加密机制。
官网网站:http://software.intel.com/en-us/articles/intel-software-evaluation-center/
l 针对Linux的IPP有2个版本:
1. Intel IPP for the Linux OS on IA-32 architecture (including low power Intel(R) architecture)
2. Intel IPP for the Linux OS on Intel(R) 64 architecture
n 目前android x86使用的是 version 7.0 32bit
l IPP静态库和动态库 以及 线程库和非线程库
- Intel IPP提供了现成的函数库,用户在使用API时只需包含相应的库然后直接调用即可,这些函数库分为动态库和静态库。在后文提到如何使用这些库。
- 这些函数库分为线程(Thread)和非线程(non-Thread)两个版本,静态库的线程版本的库名是*_t.a、非线程版本的库名是*_t.a。因为函数库需要调用的基础库在android平台上不完全被实现,所以目前android x86没有办法使用多线程版本,而是使用非线程版本。
一、IPP的基本语法规则
l 基本数据类型
n IPP中基本数据类型的格式是:
IppNN<u|s|f>[c]
其中NN表示此类型的bit长度,u和s指示是符号型还是无符号型,f表示是float类型,c表明是complex类型。图1-1给出了几种数据类型的示例。
图1-1 IPP 数据类型示例
Intel IPP按函数功能和用途的不同被分为许多小块,每块叫一个domain。每个domain有自己的头文
件,静态库,动态库和测试样例。
如图1-2所示
图1-2 IPP domain概况
Intel IPP中有一些函数执行操作时和具体的domian无关,这些函数叫核心函数。比如获取CPU的类型、特定字节数的指针对齐等。这些函数有他们自己的头文件、静态库和动态库。如图1-3所示
图1-3 IPP核心函数库 ippCore
下面是核心函数库中的几个API:
• ippCoreGetCpuType ----------- gets the CPU type
• ippGetLibVersion --------------- returns the library version
• ippCoreGetCpuClocks --------- reads the processor clock
Intel IPP函数有自己的命名规则
函数的格式如下:
ipp<data-domain><name>[_<datatype>][_<descriptor>](<parameters>);
格式中的各个字段分别为:
Data-Domain:代表输入数据类型的字符,现在版本的IPP支持以下的data-domain
n Name: 代表函数执行的操作和算法,格式如下:
<name> = <operation>[_modifier]
Operation段代表了基本操作,比如Set, DCTFwd;
Modifier段意味着在函数上的微小改动,比如CToC在函数ippsFFTInv_CToC_32fc代表进行基于复数的快速傅里叶变换,mv在函数ippmMul_mv中代表基于向量的矩阵乘法。
n Data Types:datatypes段格式如下:
<datatype> = <bit_depth><bit_interpretation>
相关的参数值为:
bit_depth = <1|8|16|32|64>
bit_interpretation = < u|s|f>[c]
u ------------ unsigned integer
s ------------ signed integer
f ------------- floating point
c ------------- complex
一个函数可以操作多个对象,如果函数操作的对象都是同一种datatype,则datatype段只能有一个值;
如果函数操作的对象间(源对象和目标对象)具有不同的data types,那么各自的datatype按照源对象和目标对象的顺序排列合成一个新的datatype,格式如下:
<datatype> = <src1Datatype>[src2Datatype][dstDatatype]
比如,函数ippsDotProd_16s16sc就是将16bit的short型和16bit的复数short型的源向量进行点乘,然后将结果保存在16bit复数short目标向量中。
n Descriptor:descriptor段描述了和操作相关联的数据。为了最小化函数中的分支、消除潜在的且多余的执行,大多数通用函数被分割成独立的原始函数,这些函数的参数就是descriptor。
IPP中的descriptor如图1-4所示
图1-4 IPP函数命名中的descriptor字段
n Parameters:parameters段就是函数的参数。它的命名有如下规则:
u 所有指针函数必须以p开头,比如,pPhase,pSrc,pSeed;指针的指针必须以pp开头,比如,ppState;定义为值得参数必须以小写字符开头,比如,val,src,srcLen。
u 参数名中新的部分必须以大写字符开头,没有下划线,比如,pSrc,lenSrc,pDlyLine。
u 每个参数的名字指定的它的功能。源目标的参数名就是pSrc或src,有时候跟着数字或名字,比如pSrc2,srcLen。输出参数的参数名就是pDst或dst,有时跟数字或名字,比如,pDst1,dstLen。
下面是几个函数名的例子:
• ippsIIR_32f_I(Ipp32f* pSrcDst, int len, IppsIIRState_32f* pState);
• ippiConvert_8u1u_C1R(const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, int dstBitOffset, IppiSize roiSize, Ipp8u threshold);
• ippmSub_vac_32f(const Ipp32f* pSrc, int srcStride0, int srcStride2, Ipp32f val, Ipp32f* pDst, int dstStride0, int dstStride2, int len, int count);
IPP的API按作用可以分为四个部分:
• signal processing
• image and video processing
• small martices and realistic rendering
• cryptography
此类函数主要包含在libipps.so中,函数以ipps开头。
ippsMalloc用来进行内存分配,它是基本函数名,通过与不同的数据类型相组合,有很多种类型的malloc函数,如:
Ipp8u* ippsMalloc_8u(int len);
Ipp16u* ippsMalloc_16u(int len);
等等。
释放内存,使用
void ippsFree(void* ptr);
复制函数,如:
IppStatus ippsCopy_1u(const Ipp8u* pSrc, int srcBitOffset, Ipp8u* pDst, int dstBitOffset, int len);
IppStatus ippsCopy_8u(const Ipp8u* pSrc, Ipp8u* pDst, int len);
IppStatus ippsCopy_16s(const Ipp16s* pSrc, Ipp16s* pDst, int len);
将vector里的数据打包成bitstream:
IppStatus ippsPackBits_32u8u(const Ipp32u* pSrcBit, const int* pSrcBits, int srcLen, Ipp8u* pDst, int dstBitOffset, int* pDstLenBit);
移动数据,如:
IppStatus ippsMove_8u(const Ipp8u* pSrc, Ipp8u* pDst, int len);
IppStatus ippsMove_16s(const Ipp16s* pSrc, Ipp16s* pDst, int len);等。
初始化vector,如:
IppStatus ippsSet_8u(Ipp8u val, Ipp8u* pDst, int len);
IppStatus ippsSet_16s(Ipp16s val, Ipp16s* pDst, int len);
将vector置为0:
IppStatus ippsZero_8u(Ipp8u* pDst, int len);
IppStatus ippsZero_16s(Ipp16s* pDst, int len);
3.1 逻辑运算
IPP中支持and,or 和xor的操作,通过区分是两个操作数是vector与vector还是vector与常量,有以下几种类型的逻辑运算:
· AndC: Computes the bitwise AND of a scalar value and each element of a vector.
· And: Computes the bitwise AND of two vectors.
· OrC: Computes the bitwise OR of a scalar value and each element of a vector.
· Or: Computes the bitwise OR of two vectors.
· XorC: Computes the bitwise XOR of a scalar value and each element of a vector.
· Xor: Computes the bitwise XOR of two vectors.
· Not: Computes the bitwise NOT of the vector elements.
· LShiftC: Shifts bits in vector elements to the left.
· RShiftC: Shifts bits in vector elements to the right.
上面列的每一种基本函数,通过与不通的数据类型相结合,又产生更多的函数,如
IppStatus ippsAndC_8u(const Ipp8u* pSrc, Ipp8u val, Ipp8u* pDst, int len);
IppStatus ippsAndC_16u(const Ipp16u* pSrc, Ipp16u val, Ipp16u* pDst, int len);
IppStatus ippsRShiftC_8u(const Ipp8u* pSrc, int val, Ipp8u* pDst, int len);
IppStatus ippsRShiftC_16s(const Ipp16s* pSrc, int val, Ipp16s* pDst, int len);
3.2算术运算函数
基本函数名有AddC ,Add ,AddProductC , AddProduct, MulC, Mul, SubC , SubCRev,Sub,DivC,DivCRev,Div,Div_Round,Abs,Sqr,Sqrt,Cubrt,Exp,Ln,10Log10,SumLn,Arctan,Normalize,Cauchy,CauchyD,CauchyDD2。其中C标志与3.1节中的意义相同,表示常量。与数据类型组合后的例子有:
IppStatus ippsAddC_32f(const Ipp32f* pSrc, Ipp32f val, Ipp32f* pDst, int len);
IppStatus ippsAddC_64f(const Ipp64f* pSrc, Ipp64f val, Ipp64f* pDst, int len);
IppStatus ippsAddProduct_32f(const Ipp32f* pSrc1, const Ipp32f* pSrc2, Ipp32f* pSrcDst, int len);
IppStatus ippsAddProduct_64f(const Ipp64f* pSrc1, const Ipp64f* pSrc2, Ipp64f* pSrcDst, int len);
3.3转换函数
转换函数包含的内容有排序、数据类型的转换、vector的Join操作、提取或构造复数、计算复向量的共轭、笛卡尔坐标与极坐标的转换等。各函数的简介如下:
· SortAscend, SortDescend:升序和降序排序
· SortIndexAscend, SortIndexDescend: 带索引的排序
· SortRadixAscend, SortRadixDescend: 使用radix sorting algorithm进行排序。
· SortRadixIndexAscend, SortRadixIndexDescend: 间接使用radix sorting algorithm 排序。
· SwapBytes: 反转vector里字节序。
· Convert: 转换vector里数据类型
· Join: 将vector里float数据转换成int型。
· JoinScaled: 同Join,但vector里的数据是带scale参数的。
· SplitScaled: 与JoinScaled进行相反的操作。
· Conj: 计算共轭向量。
· ConjFlip: 计算共轭向量,并按相反位置存储。
· Magnitude: 计算复向量每个元素的大小。
· MagSquared: 计算复向量每个元素的大小的平方。
· Phase: 计算复向量每个元素的相角。
· PowerSpectr: 计算 复向量的power spectrum.
· Real: 计算复向量的实数部分。
· Imag: 计算复向量的虚数部分。.
· CartToPolar: 笛卡尔坐标转极坐标。
· PolarToCart: 极坐标转笛卡尔坐标。
· Flip: 将vector里元素倒序存放。
3.4 统计类函数
该类函数主要是是计算vector里的最大值、最小值、平均值和方差等。
· Max: 返回最大值。
· Sum:计算元素之和。
· MaxIndx: 返回最大元素及索引。
· Mean:返回vector的平均值。
· DotProd:计算两个vector的点积。
3.5字符串操作函数
IPP提供了丰富的函数进行文本操作,既有简单的字符串操作函数,像字符串的相等比较、查找、删除等,也有复杂的使用正则表达式进行的模式匹配。基本函数名有:
· Find, FindRev: 查找子串的第一次出现位置。
· Insert: 在一个字符串中插入字符串。
· Remove: 从字符串中删除指定数目的字符。
· Compare: 比较两个字符串是否相等。
· RegExpFind: 查找符合指定正则表达式的子串。
· RegWxpReplace:按照正则表达式查找并替换子串。
这些基本函数名也可以结合不同的数据类型,如:
IppStatus ippsFind_8u(const Ipp8u* pSrc, int len, const Ipp8u* pFind, int lenFind, int* pIndex);IppStatus ippsFind_Z_8u(const Ipp8u* pSrcZ, const Ipp8u* pFindZ, int* pIndex);
IppStatus ippsFind_16u(const Ipp16u* pSrc, int len, const Ipp16u* pFind, int lenFind, int* pIndex);IppStatus ippsFind_Z_16u(const Ipp16u* pSrc, const Ipp16u* pFind, int* pIndex);
IppStatus ippsRegExpReplace_8u(const Ipp8u* pSrc, int* pSrcLenOffset, Ipp8u* pDst, int* pDstLen, IppRegExpFind* pFind, int* pNumFind, IppRegExpState* pRegExpState, IppRegExpReplaceState* pReplaceState);
3.6 其他函数
IPP提供了其他一些高级函数:
1)信号过滤函数,如
IppStatus ippsConv_32f(const Ipp32f* pSrc1, int src1Len, const Ipp32f* pSrc2, int src2Len, Ipp32f* pDst);
用来计算两向量的卷积。
2)信号变换函数,如FFTFwd_RToPack, FFTFwd_RToPerm, FFTFwd_RToCCS等函数用来进行快速傅立叶变换。
3)数据压缩函数,如
ippsVLCEncodeBlock_16s1u (const Ipp16s* pSrc, int srcLen, Ipp8u** ppDst, int* pDstBitsOffset, const IppsVLCEncodeSpec_32s* pVLCSpec);
对数据进行VLC编码,
IppStatus ippsEncodeHuff_8u(const Ipp8u* pSrc, int srcLen, Ipp8u* pDst, int* pDstLen, IppHuffState_8u* pHuffState);
进行Huffman编码。
4)Speech coding和 Audio coding.
此类函数主要包含在libippi.so中,函数以ippi开头。
这部分使用的内存分配函数原型为:
Ipp<datatype>* ippiMalloc_<mod>(int widthPixels, int heightPixels, int* pStepBytes);
除了可以与不同的datatype结合外,还有不同的mode:8u_C1,8u_AC4, 322sc_AC3等等。A就代表alpha通道,C跟上后面的数字表示通道个数。
释放内存,使用
void ippiFree(void* ptr);
Convert:将像素数据类型转换为另一类型,如
IppStatus ippiConvert_1u8u_C1R(const Ipp8u* pSrc, int srcStep, int srcBitOffset, Ipp8u* pDst, int dstStep, IppiSize roiSize);
Set:初始化Image像素为一固定值,如
IppStatus ippiConvert_1u8u_C1R(const Ipp8u* pSrc, int srcStep, int srcBitOffset, Ipp8u* pDst, int dstStep, IppiSize roiSize);
Copy:在两个buffer之间复制像素,如
IppStatus ippiCopy_<mod>(const Ipp<datatype>* pSrc, int srcStep, Ipp<datatype>* pDst, int dstStep, IppiSize roiSize);
Transpose:对图像进行转置操作,如IppStatus ippiTranspose_<mod>(const Ipp<datatype>* pSrc, int srcStep, Ipp<datatype>* pDst, int dstStep, IppiSize roiSize);
3.1 算法运算函数
这部分函数与ipps中的数据运算类似,只是ipps是对象是一维的vector,这部分的运算对象 是二维的image,主要函数简介如下:
· Add: 将两个image的像素值相加。
· AddC: 将一个常量与image中的每个像素值相加。
· Mul: Multiplies pixel values of two images.
· MulC: Multiplies pixel values of an image by a constant.
· Sub: Subtracts pixel values of two images.
· SubC: Subtracts a constant from pixel values of an image.
· Div: Divides pixel values of an image by pixel values of another image.
· DivC: Divides pixel values of an image by a constant.
· Abs: 取一个image各像素的绝对值,构造新的image。
· AbsDiff: 计算两image的像素的绝对值差。
· AbsDiffC: Calculates absolute difference between image and scalar value.
· Sqr: Squares pixel values of an image and writes them into the destination image.
· DotProd: Computes the dot product of pixel values of two source images.
3.2 逻辑运算函数
主要有如下函数
· And: Performs a bitwise AND operation between corresponding pixels of two images.
· AndC: Performs a bitwise AND operation of each pixel with a constant.
· Or: Performs bitwise inclusive OR operation between pixels of two source buffers.
· OrC: Performs a bitwise inclusive OR operation between each pixel of a buffer and a constant.
· Xor: Performs bitwise exclusive OR operation between pixels of two source buffers.
· XorC: Performs a bitwise exclusive OR operation between each pixel of a buffer and a constant.
· Not: Performs a bitwise NOT operation on each pixel of a source buffer.
· RShiftC: Shifts bits in pixel values to the right.
· LShiftC: Shifts bits in pixel values to the left.
3.3 alpha构造图像函数
使用两个image的alpha值来从两个image中生成新的image,主要有四类生成类型:
AlphaComp: 使用两个image中的alpha值来生成image。
AlphaCompC: 使用一个指定的alpha数据生成image
AlphaPremul: 首先使用一个图像的像素中颜色信息部分乘以本身的alpha值。
AlphaPremulC: 首先使用一个图像的像素中颜色信息部分乘以一个固定的alpha值。
下面给出几个实例:
IppStatus ippiAlphaComp_<mod>(const Ipp<datatype>* pSrc1, int src1Step, const Ipp<datatype>* pSrc2, int src2Step, Ipp<datatype>* pDst, int dstStep, IppiSize roiSize, IppiAlphaType alphaType);
IppStatus ippiAlphaComp_<mod>(const Ipp<datatype>* pSrc1, int src1Step, const Ipp<datatype>* pSrc2, int src2Step, Ipp<datatype>* pDst, int dstStep, IppiSize roiSize, IppiAlphaType alphaType);
4.1 颜色模型的转换
IPP支持丰富的颜色模型,包括RGB,CMYK,YUV,YCbCr,YCCK,PhotoYCC,YCoCg,HSV,HLS,CIE XYZ, CIE LUV 和CIE Lab等,并提供了它们之间的转换函数,如
RGBToYUV, YUVToRGB,RGBToXYZ,RGBToHLS,HLSToRGB,BGRToHLS, HLSToBGR等。
对于不同的颜色格式IPP也提供了支持,如BRG, RGB, RGB565,RGB555, YCbCr422, YCbCr420, YCbCr411, YUV planar格式和YUV packet格式等。它们之间的转换函数有:RGBToRGB565, BGRToBGR565, RGB565ToRGB, BGR565ToBGR, YCbCr422, YCbCr422ToYCrCb422,YCbCr422ToCbYCr422,YCbCr422ToYCbCr420等。
4.2 灰度图像的转换
RGBToGray: 使用IPP内部固定的转换系统将彩色图像转换成灰度图像。
ColorToGray: 使用自定义的转换系数将彩色图像转换成灰度图像。.
CFAToRGB: 使用color filter array (CFA)将灰度图像还原成彩色图像。
DemosaicAHD: 使用AHD 算法将CFA image转换成彩色图像。
IPP提供了快速傅立叶变换(FFT), 离散傅立叶变换(DFT),离散余弦变换(DCT)以及小波变换(wavelet transform), 如:
FFTFwd,DFTFwd , DCTFwd, WTFwd等。
IPP图像压缩使用了JPEG, JPEG2000,JPEG XR的标准。
6.1 JPEG编码
1)颜色转换
这些函数是针对JPEG编码的。彩色图像与灰度图像的转换有:
RGBToY_JPEG:Converts an RGB image to gray scale.
BGRToY_JPEG:Converts a BGR image to gray scale.
RGB与YCrCb之间的转换有:
RGBToYCbCr_JPEG:Converts an RGB image to YCbCr color model.
YCbCrToRGB_JPEG:Converts an YCbCr image to the RGB color model.
RGB565ToYCbCr_JPEG, RGB555ToYCbCr_JPEG:Convert a 16-bit RGB image to YCbCr color model.
等。还有其他类型的一些颜色转换函数,如
CMYKToYCCK_JPEG:Converts a CMYK image to the YCCK color model.
YCCKToCMYK_JPEG:Converts an YCCK image to the CMYK color model.
2)混合颜色转换
这类函数在进行颜色转换时,还可以进行sampling和level shift等操作,如
IppStatus ippiRGBToYCbCr444LS_MCU_8u16s_C3P3R(const Ipp8u* pSrcRGB, int srcStep, Ipp16s* pDstMCU[3]);
在完成将RGB向YCbCr444转换后,通过level shift将源数据表示范围由[0..255]转换到带符号的[-128..127],同时创建一个444 MCU。其他函数类似,如:
· RGBToYCbCr422LS_MCU: Converts RGB images to YCbCr color model and creates 422 MCU.
· RGBToYCbCr411LS_MCU :Converts RGB images to YCbCr color model and creates 411 MCU.
· BGRToYCbCr444LS_MCU: Converts BGR images to YCbCr color model and creates 444 MCU.
等。
3)无损JPEG压缩
它使用的是Huffman编码,主要函数如下:
· DiffPredFirstRow_JPEG :Computes the differences between input sample and predictor for the first line
· DiffPredRow_JPEG: Computes the differences between input sample and predictor for all lines but the first.
· ReconstructPredFirstRow_JPEG :Reconstructs samples from the decoded differences between input samples and predictor for the first line.
· ReconstructPredRow_JPEG :Reconstructs samples from the decoded differences between input samples and predictor for all lines but the first.
· GetHuffmanStatisticsOne_JPEG :Computes Huffman symbol statistics
· EncodeHuffmanOne_JPEG :Performs Huffman encoding of one difference.
· DecodeHuffmanOne_JPEG :Decodes one Huffman coded difference.
· EncodeHuffmanRow_JPEG : Performs Huffman encoding of one row of differences for each color component in the JPEG scan.
· DecodeHuffmanRow_JPEG: Decodes one row for each color component of Huffman coded differences
4)JPEG2000 熵编码与解码
它的函数举例说明如下:
· IppStatus ippiEncodeInitAlloc_JPEG2K(IppiEncodeState_JPEG2K** pState, IppiSize codeBlockMaxSize):初始化熵编码state structure。
· IppStatus ippiEncodeFree_JPEG2K(IppiEncodeState_JPEG2K* pState):释放申请有memory。
IppStatus ippiEncodeLoadCodeBlock_JPEG2K_32s_C1R:执行编码过程。
· IppStatus ippiDecodeCodeBlock_JPEG2K_1u32s_C1R:解码指定的block.
· IppStatus ippiDecodeCBProgrStep_JPEG2K:执行一步解码的操作。
可处理的视频格式包括MPEG-1, MPEG-2, MPEG-4, DV, H.261, H.263, H.264 , AVS, VC-1等。
l small martices and realistic rendering
此类函数主要包含在libippm.so中,函数以ippm开头。
常量、常量数组
向量、向量数组
矩阵、矩阵数组
转置矩阵、转置矩阵数组
Copy:将一个向量拷贝至另一个向量
IppStatus ippmCopy_va_32f_SS(const Ipp32f* pSrc, int srcStride0, int srcStride2, Ipp32f* pDst, int dstStride0, int dstStride2, int len, int count);
Extract:提取出ROI部分
IppStatus ippmExtract_v_32f(const Ipp32f* pSrc, int srcStride2, Ipp32f* pDst, int len);
LoadIdentity:初始化单位矩阵
IppStatus ippmLoadIdentity_ma_32f(const Ipp32f* pDst, int dstStride0, int dstStride1, int dstStride2, int width, int height, int count);
Add:将常量和向量或向量和向量相加
IppStatus ippmAdd_vc_32f(const Ipp32f* pSrc, int srcStride2, Ipp32f val, Ipp32f* pDst, int dstStride2, int len);
Sub:从向量减去一个常量 或 从一个常量减去向量 或 向量减向量
IppStatus ippmSub_vc_32f(const Ipp32f* pSrc, int srcStride2, Ipp32f val, Ipp32f* pDst, int dstStride2, int len);
Mul:向量和常量相乘
IppStatus ippmMul_vc_32f(const Ipp32f* pSrc, int srcStride2, Ipp32f val, Ipp32f* pDst, int dstStride2, int len);
Transpose:计算矩阵的转置
IppStatus ippmTranspose_m_32f(const Ipp32f* pSrc, int srcStride1, int srcStride2, int width, int height, Ipp32f* pDst, int dstStride1, int dstStride2);
Invert:翻转矩阵
IppStatus ippmInvert_m_32f(const Ipp32f* pSrc, int srcStride1, int srcStride2, Ipp32f* pBuffer, Ipp32f* pDst, int dstStride1, int dstStride2, int widthHeight);
FrobNorm:计算行列式
IppStatus ippmFrobNorm_m_32f(const Ipp32f* pSrc, int srcStride1, int srcStride2, int width, int height, Ipp32f* pDst);
Mul:矩阵相乘
IppStatus ippmMul_mc_32f(const Ipp32f* pSrc, int srcStride1, int srcStride2, Ipp32f val, Ipp32f* pDst, int dstStride1, int dstStride2, int width, int height);
Add:矩阵相加
IppStatus ippmAdd_mm_32f(const Ipp32f* pSrc1, int src1Stride1, int src1Stride2, const Ipp32f* pSrc2, int src2Stride1, int src2Stride2, Ipp32f* pDst, int dstStride1, int dstStride2, int width, int height);
Sub:矩阵相减
IppStatus ippmSub_mm_32f(const Ipp32f* pSrc1, int src1Stride1, int src1Stride2, const Ipp32f* pSrc2, int src2Stride1, int src2Stride2, Ipp32f* pDst, int dstStride1, int dstStride2, int width, int height);
LUDecomp:将矩阵分解为上三角或下三角矩阵
IppStatus ippmLUDecomp_m_32f(const Ipp32f* pSrc, int srcStride1, int srcStride2, int* pDstIndex, Ipp32f* pDst, int dstStride1, int dstStride2, int widthHeight);
LUBackSubst:计算矩阵的线性方程
IppStatus ippmLUBackSubst_mv_32f(const Ipp32f* pSrc1, int src1Stride1, int src1Stride2, int* pSrcIndex, const Ipp32f* pSrc2, int src2Stride2, Ipp32f* pDst, int dstStride2, int widthHeight);
CholeskyDecomp: 将对称矩阵进行Cholesky分解
IppStatus ippmCholeskyDecomp_m_32f(const Ipp32f* pSrc, int srcStride1, int srcStride2, Ipp32f* pDst, int dstStride1, int dstStride2, int widthHeight);
CholeskyBackSubst:利用Cholesky计算矩阵线性方程
IppStatus ippmCholeskyBackSubst_mv_32f(const Ipp32f* pSrc1, int src1Stride1, int src1Stride2, const Ipp32f* pSrc2, int src2Stride2, Ipp32f* pDst, int dstStride2, int widthHeight);
QRDecomp:将矩阵进行QR分解
IppStatus ippmQRDecomp_m_32f(const Ipp32f* pSrc, int srcStride1, int srcStride2, Ipp32f* pBuffer, Ipp32f* pDst, int dstStride1, int dstStride2, int width, int height);
QRBackSubst:解决QR分解矩阵的最小平方问题
IppStatus ippmQRBackSubst_mv_32f(const Ipp32f* pSrc1, int src1Stride1, int src1Stride2, Ipp32f* pBuffer, const Ipp32f* pSrc2, int src2Stride2, Ipp32f* pDst, int dstStride2, int width, int height);
EigenValuesVectorsSym:找出矩阵的特征值和特征向量
IppStatus ippmEigenValuesVectorsSym_m_32f (const Ipp32f* pSrc, int srcStride1, int srcStride2, Ipp32f* pBuffer, Ipp32f* pDstVectors, int dstStride1, int dstStride2, Ipp32f* pDstValues, int widthHeight);
EigenValuesSym:找出特征值
IppStatus ippmEigenValuesSym_m_32f (const Ipp32f* pSrc, int srcStride1, int srcStride2, Ipp32f* pBuffer, Ipp32f* pDstValues, int widthHeight);
EigenValuesVectors:找出特征值,左右特征向量
IppStatus ippmEigenValuesVectors_m_32f (const Ipp32f* pSrc, int srcStride1, int srcStride2, Ipp32f* pDstVectorsRight, int dstRightStride1, int dstRightStride2, Ipp32f* pDstVectorsLeft, int dstLeftStride1, int dstLeftStride2, Ipp32f* pDstValuesRe, Ipp32f* pDstValuesIm, int widthHeight, Ipp8u* pBuffer);
EigenValues:找出特征值
IppStatus ippmEigenValues_m_32f (const Ipp32f* pSrc, int srcStride1, int srcStride2, Ipp32f* pDstValuesRe, Ipp32f* pDstValuesIm, int widthHeight, Ipp8u* pBuffer);
EigenValuesVectorsGetBufSize:计算函数EigenValuesVectors的buffersize
IppStatus ippmEigenValuesVectorsGetBufSize_32f (int widthHeigh, int* pSizeBytes);
EigenValuesGetBufSize:计算函数EigenValues的buffersize
IppStatus ippmEigenValuesGetBufSize_32f (int widthHeight, int* pSizeBytes);
Len:计算2D,3D,4D向量的长度
IppStatus ippmLen_v2_32f (const Ipp32f* pSrc, Ipp32f* pDst);
LenSqr:计算2D,3D,4D向量的平方长度
IppStatus ippmLenSqr_v2_32f (const Ipp32f* pSrc, Ipp32f* pDst);
DotProduct:计算2D,3D,4D向量的点乘
IppStatus ippmDotProduct_v2_32f (const Ipp32f* pSrc1, const Ipp32f* pSrc2, Ipp32f* pDst);
Add:把两个2D,3D,4D向量相加
IppStatus ippmAdd_v2_32f (const Ipp32f* pSrc1, const Ipp32f* pSrc2, Ipp32f* pDst);
Sub:把两个2D,3D,4D向量相减
IppStatus ippmSub_v2_32f (const Ipp32f* pSrc1, const Ipp32f* pSrc2, Ipp32f* pDst);
Min:计算两个2D,3D,4D向量最小分量
IppStatus ippmMin_v2_32f (const Ipp32f* pSrc1, const Ipp32f* pSrc2, Ipp32f* pDst);
Max:计算两个2D,3D,4D向量最大分量
IppStatus ippmMax_v2_32f (const Ipp32f* pSrc1, const Ipp32f* pSrc2, Ipp32f* pDst);
MulC:将2D,3D,4D向量和常数相乘
IppStatus ippmMulC_v2_32f (const Ipp32f* pSrc, Ipp32f scale, Ipp32f* pDst);
InterpolationLinear:执行两个2D,3D,4D向量的线性内插
IppStatus ippmInterpolationLinear_v2_32f (const Ipp32f* pSrc1, const Ipp32f* pSrc2, Ipp32f scale, Ipp32f* pDst);
Normalize:将2D,3D,4D向量标准化
IppStatus ippmNormalize_v2_32f (const Ipp32f* pSrc, Ipp32f* pDst);
CrossProduct:将2D,3D,4D向量进行叉乘
IppStatus ippmCrossProduct_v2_32f (const Ipp32f* pSrc1, const Ipp32f* pSrc2, Ipp32f* pDst);
Invert:将4X4矩阵反转
IppStatus ippmInvert_m4_32f (const Ipp32f* pSrc, Ipp32f* pDstDet, Ipp32f* pDst);
Identity:初始化一个4X4单位矩阵
IppStatus ippmIdentity_m4_32f (Ipp32f* pDst);
IsIdentity:检查一个4X4矩阵是不是单位矩阵
IppStatus ippmIsIdentity_m4_32f (const Ipp32f* pSrc, Ipp32s* pDst);
Det:计算一个4X4矩阵的行列式
IppStatus ippmDet_m4_32f (const Ipp32f* pSrc, Ipp32f* pDst);
DES/TDES
Rijndael
AES-CCM
AES-GCM
Blowfish
Twofish
RC5*
ARCFour
MD5GetSize:获取IppsMD5State上下文的大小
IppStatus ippsMD5GetSize(int *pSize);
MD5Init:初始化IppsMD5State
IppStatus ippsMD5Init(IppsMD5State* pCtx);
MD5Pack,MD5Unpack:将IppsMD5State打包进一个用户定义的buffer或者从buffer中取出打开
IppStatus ippsMD5Pack (const IppsMD5State* pCtx, Ipp8u* pBuffer);
MD5Duplicate:将IppsMD5State上下文拷贝至另一个
IppStatus ippsMD5Duplicate(const IppsMD5State* pSrcCtx, IppsMD5State* pDstCtx);
MD5MessageDigest:生成MD5函数
IppStatus ippsMD5MessageDigest(const Ipp8u *pSrcMesg, int mesgLen,
Ipp8u *pMD);
还提供了SHA1,SHA224,SHA256,SH384和SH512的相关操作
Add_BNU:将两个等长的无符号整形大数相加
IppStatus ippsAdd_BNU(const Ipp32u *a, const Ipp32u *b, Ipp32u *r, int n, Ipp32u * carry);
Sub_BNU:将两个等长的无符号整形大数相减
IppStatus ippsSub_BNU(const Ipp32u *a, const Ipp32u *b, Ipp32u *r, int n, Ipp32u * carry);
MulOne_BNU:将两个等长的无符号整形大数相乘
IppStatus ippsMulOne_BNU(const Ipp32u *a, Ipp32u *r, int n, Ipp32u w, Ipp32u *carry);
Mul_BNU4:将两个4*32bit的无符号整形相乘
IppStatus ippsMul_BNU4(const Ipp32u *a, const Ipp32u *b, Ipp32u *r);
Mul_BNU8:将两个8*32bit的无符号整形相乘
IppStatus ippsMul_BNU8(const Ipp32u *a, const Ipp32u *b, Ipp32u *r);
Div_64u32u:将一个64bit的无符号整形除以32bit的无符号整形
IppStatus ippsDiv_64u32u(Ipp64u a, Ipp32u b, Ipp32u *q, Ipp32u *r);
GetOctString_BNU:将一个无符号整形大数转化为一个字符串
IppStatus ippsGetOctString_BNU(const Ipp32u* pBNU, int bnuSize, Ipp8u* pOctStr, int strLen);
SetOctString_BNU:将一个字符串转化为一个无符号整形大数
IppStatus ippsSetOctString_BNU(const Ipp8u* pOctStr, int strLen, Ipp32u* pBNU, int* pBNUsize);
Cmp_BN:比较两个大数的大小
IppStatus ippsCmp_BN(const IppsBigNumState *pA, const IppsBigNumState *pB, Ipp32u *pRsult);
Add_BN:将两个整形大数相加
IppStatus ippsCmp_BN(const IppsBigNumState *pA, const IppsBigNumState *pB, Ipp32u *pRsult);
Sub_BN:将两个整形大数想减
IppStatus ippsSub_BN(IppsBigNumState *a, IppsBigNumState *b, IppsBigNumState * r);
Mul_BN:将两个整形大数相乘
IppStatus ippsMul_BN(IppsBigNumState *a, IppsBigNumState *b, IppsBigNumState * r);
Div_BN:将两个大数整形相处
IppStatus ippsDiv_BN(IppsBigNumState *a, IppsBigNumState *b, IppsBigNumState * q, IppsBigNumState *r);
Mod_BN:取模
IppStatus ippsMod_BN(IppsBigNumState *a, IppsBigNumState *m, IppsBigNumState * r);
RSAGetSize:获取IppsRSAState Context的大小
IppStatus ippsRSAGetSize(int nBitsN, int nBitsP, IppRSAKeyType flag, int* pSize);
RSAInit:初始化IppsRSAState
IppStatus ippsRSAInit(int nBitsN, int nBitsP, IppRSAKeyType flag, IppsRSAState* pCtx);
RSASetKey:为创建的RSA Context创建key
IppStatus ippsRSASetKey(const IppsBigNumState* pBN, IppsRSAKeyTag tag, IppsRSAState* pCtx);
RSAGetKey:获取RSA Context中的key
IppStatus ippsRSAGetKey(IppsBigNumState* pBN, IppsRSAKeyTag tag, const IppsRSAState* pCtx);
RSAEncrypt:执行RSA加密操作
IppStatus ippsRSAEncrypt(const IppsBigNumState* pX, IppsBigNumState* pY, IppsRSAState* pCtx);
RSADecrypt:执行RSA解密操作
IppStatus ippsRSADecrypt(const IppsBigNumState* pX, IppsBigNumState* pY, IppsRSAState* pCtx);
DLPGetSize: 获取IppsDLPState context的大小
IppStatus ippsDLPGetSize(int peBits, int reBits, int *pSize);
DLPInit:初始化IppsDLPState context
IppsStatus IppsDLPInit(int peBits, int reBits, IppsDLPState* pCtx);
DLPPublicKey:计算DL-based的key
IppStatus ippsDLPPublicKey(const IppsBigNumState* pPrivate, IppsBigNumState* pPublic, IppsDLPState* pCtx);
PS:在PC上安装完IPP之后,
在ippDir/comopser_xe_2011_sp1/Documentation/en_US/ipp/ipp_manual/index.html 中有具体的API介绍,使用时可以参考。(ippDir通常为/opt/intel)。
n 步骤一:在网站http://software.intel.com/en-us/articles/intel-software-evaluation-center/下载Intel® Integrated Performance Primitives (Intel® IPP) for Linux*,选择32位版本l_ipp_7.0.6.273_ia32.tgz。
n 步骤二: 解压后,进入目录运行install.sh,在ubuntu上安装,安装过程使用默认设置。安装完成后ippDir默认为/opt/intel。
n 步骤三: 将ubuntu上的 ippDir/composer_xe_2011_sp1.8.273/IPP/include和ippDir/composer_xe_2011_sp1.8.273/IPP/lib目录及包含的所有文件拷贝到android source code的external/ipp/下。
l 在Android上使用IPP静态库 (以在Camera HAL中调用IPP为例)
n 步骤一:修改Camera HAL 中的Android.mk:
LOCAL_C_INCLUDES += \
external/ipp/include
LOCAL_LDFLAGS:= \
external /ipp/lib/ia32/libippi_l.a \
external /ipp/lib/ia32/libipps_l.a \
external /ipp/lib/ia32/libippm_l.a \
external /ipp/lib/ia32/libippcore_l.a \
external /ipp/lib/ia32/libippcc_l.a
n 步骤二:在要使用IPP function的文件中(.c或.h)包括头文件<ipp.h>
n 步骤三: 一定要先调用ippStaticInit()进行静态库的初始化,才能调用IPP其他函数。否则,链接无法通过。比如在CameraHardware.cpp中startPreview()时调用ippStaticInit()。之后就能直接调用IPP中的function.
l 在Android上使用IPP动态库 (以在Camera HAL中调用IPP为例)
n 步骤一:将IPP的.a 重新编译成.so
u 在external/ipp/下新建ippxxx.so对应的目录,比如要生成libippi.so,libippcore.so,libippcc.so等,建立目录ippi,ipps,ippcc等。
u 每个目录下新建init.c,在其中调用ippStaticInit.编辑相应目录下Android.mk,在 LOCAL_SRC_FILES中添加init.c文件,在LOCAL_LDFLAGS添加library.script文件和该so所依赖的.a文件,如
LOCAL_LDFLAGS:= \
$(LOCAL_PATH)/library.scrip \
external/composer_xe/ipp/lib/ia32/libippcc_l.a \
external/composer_xe/ipp/lib/ia32/libippcore_l.a
u 编辑每个目录下的library.script 文件,在其中加入该库需要导出的函数,比如在ipps/library.script中添加:
EXTERN( ippsCopy_8u )
……
u 执行编译。
n 步骤二:调用生成的.so
u 在Android.mk中LOCAL_SHARED_LIBRARIES上添加上相应的ippxxxso.
u 在source file中 include <ipp.h> 后,就可以直接调用IPP的函数了。
在Camera的preview中加入了IPP,使用IPP的API---ippiYCbCr422ToBGR565() 取代原有的convert函数进行colorspace的转化。经测试,结果如图4-1,表格中的数据代表处理每帧图片所消耗的时间。
图 4-1 Camera Preview 加入IPP后 performance对比
从图中可以看出,随着机器分辨率的提升,处理每帧图片所耗费的时间就越久;于此同时,使用IPP后performance的提升就越明显。
在frameworks/base/media/libstagefright/colorconversion/ColorConverter.cpp文件中,使用IPP API --- ippiYCbCr420ToBGR_8u_P3C4R代替原有转换方法。利用现有的两个视频文件进行测试,测试结果:
播放视频A时:no ipp每帧的耗时是37ms,use ipp是18ms;
播放视频B时:no ipp每帧的耗时是18ms,use ipp是9ms。
但就人眼观察的角度来看,使用IPP时的卡顿现象比no ipp稍微少一点,但是差别不大。