C/C++ 多媒体开发 实战宝典
纲要:
1) Code opt : C/MMX/MMX2/SSE2
a) Opt principle
b) TABLE (mpeg2-tabtab)
c) SIMD introduction
2) 数字压缩基础
a) RGB,YUV
b) BMP,GIF,JPEG
c) MPEG2/MPEG4/H264
3) GET BITS
a) C
b) X86,SHLD
c) MMX
4) CABAC
a) C
b) MMX
5) IDCT
a) PRIM
b) REF
c) FAST-IDCT
d) JR-IDCT
e) JP-IDCT
f) TB-IDCT
g) MMX AND SSE2 IDCT
6) MC
a) REF
b) C AVGB
c) MMX
d) BYTE ALIGNED MMX
7) TRANSPOSE
a) REF
b) C SIMPLE
c) C FAST
d) MMX/SSE2
8) DE-BLOCK FILTER
a) C
b) MMX CASE
9) SUPER-ERROR SKIP
10) DEINTERLACE
a) SIMPLE
b) MOTION DETECT
c) MD+SMOOTH
11)SHARP/SMOOTH/STECH/ROTATE
a) SHARP FILTER
b) SMOOTH FILTER
c) FAST/BI-LINER/BI-CUBIC
d) ROTATE
12) OBJECT TRACKING
a) Principle
b) Optical flow
c) TGMC
13) AUDIO: LONG INTEGER
a) PMADDWD 47 BITS INTEGER, AC3 DECODE;
14) SUPER LONG INTEGER
a) SUPERPI
b) RSA
15) AUDIO: RESAMPLE
16) STRING SEARCH
a) PSABDW
17) CACHE
a) MC CASE;
b) De-block case
18) MULTI-THREAD
a) Principle
b) Data exchange
19) DIRECTX
a) Direct draw
b) Direct 3d
c) Direct sound
20) DIRECTSHOW
a) Filter develop
21) NET WORK STREAM VIDEO, TCP/UDP
a) NAT hole
22) INFRA STRCTURE
a) Principle
b) Time cycle;
大整数运算
1.1 大整数的表示
在 32 位字长的系统里,基本数据类型有:
8 位数,BYTE,单字节:char,unsigned char。
16 位数,WORD,字:short,unsigned short。
32 位数,DWORD,双字:int,unsigned int。
64 位数,QWORD,四字:__int64, unsigned __int64
这些基本数据类型的运算可以被机器指令所直接支持。
在 x86 平台上,多个字节的数据存放顺序是,低位数据存放在低位地址。
比如,0x00010203, 在内存中的存放顺序是 03,02,01,00。
照此类推,128 位整数,8 字,16 字节,0x000102030405060708090A0B0C0D0E0F
的 内 存 映 像 是 : 0F ,
0E,0D,0C,0B,0A,09,08,07,06,05,04,03,02,01,00。
位数是 2 的整数次方,64 位,128 位,256 位等整数,我们称之为规范整数。
进行大整数的四则运算的时候,一个基本的原理就是把大整数运算降解为 32 位四则运
算的复合运算。降解的方式可以是位数减半,即 256 位降解为 128 位,128 位降解为 64 位,
直到降解为机器指令支持范围内的整数。这样的降解过程用到的所有的中间变量都是规范
的整数。也可以是从高到低,每次降解 32 位。这样的话在降解过程中我们会使用到 256-
32=224,224-32=192,192-32=160 等长度不等于 2 的整数次方的整数,我们称之为不规范
的整数。减半降解运算过程比较容易理解,而逐次降解则会获得较好的性能。
大整数的符号。一般来说,大整数运算中,负数的使用是非常少的。如果要使用符号
的话,同基本数据一样,最高位表示符号,剩余的数位用来表示有效值。
1.2 大整数加法
1.2.0 在大整数四则运算中,加法是基本的运算,也最容易实现。只要处理好进位数据
就可以了。在机器指令层面上,x86 平台有 ADC(带进位加), JC(进位条件跳转),
CMOVC(进位条件复制)等丰富指令的高效支持。在 C 语言层面上,我们用无符号
__int64 类型来存贮两个 32 位整数之和,低 32 位(0-31)是结果,第 32 位是进位。有兴趣的
话,读者可以通过跟踪/反编译 C 代码来研究以上机器指令的使用方法。
1.2.1 大整数加 32 位整数:
/*****************************************************************************
LX_RESULT
large_int_add_pass_c32( BYTE* psa,DWORD dwsb,BYTE* psd,DWORD* pca,int nBytes )
Chinese:
返回值:LX_OK
输入参数:psa, 存放第一个操作数的地址。
输入参数:dwsb, 第二个操作数,32 位无符号整数。
输出参数:psd,存放运算结果的地址。
输出参数:pca,存放进位数据的 32 位无符号整数地址。
输入参数:nBytes,大整数字节数。
English:
Return value: LX_OK;
Input Parameters: psa, the memory address of first operand.
Input Parameters:dwsb,32 bits unsigned integer, second operand.
Output Parameters: psd, address to save results.
Output Parameters: pca, address of 32 bits unsigned integer, to save carry flag.
Input Parameters: nBytes, the legth in bytes of the integer saved in psa;
*****************************************************************************/
LX_RESULT
large_int_add_pass_c32( BYTE* psa,DWORD dwsb,BYTE* psd,DWORD* pca,int nBytes )
{
ULARGE_INTEGER uld;
DWORD dwA;
DWORD dwC = 0;
DWORD* pwa = (DWORD*)psa;
DWORD* pwd = (DWORD*)psd;
//如果目标地址不等于大整数源地址,首先复制源操作数到目标地址。
if( psd != psa ) {
memcpy(psd,psa,nBytes);
}
dwA = *pwa++; // 取第一个 DWORD;
uld.QuadPart = (__int64)dwA + dwsb ; // 用 64 位整数存放加法结果;
*pwd++ = (DWORD)( uld.LowPart); // 低 32 位作为结果输出;
dwC = (DWORD)(uld.HighPart); // 高 32 位为进位。
// 当存在进位,并且位数不超过整数长度时,执行循环。
while( dwC && (nBytes = nBytes - 4) > 0 ){
dwA = *pwa++;
uld.QuadPart = (__int64)dwA + dwC;
*pwd++ = (DWORD)( uld.LowPart);
dwC = (DWORD)(uld.HighPart);
}
*pca = dwC; // 输出进位;
return LX_OK;
}
1.2.2 大整数加大整数:
/*****************************************************************************
LX_RESULT
large_int_add_c32( BYTE* psa,BYTE* psb,BYTE* psd,DWORD* pca,int nBytes )
Chinese:
返回值:LX_OK
输入参数:psa, 存放第一个操作数的地址。
输入参数:psb,第二个操作数的地址。
输出参数:psd,存放运算结果的地址。
输出参数:pca,存放进位数据的 32 位无符号整数地址。
输入参数:nBytes,大整数字节数。
English:
Return value: LX_OK;
Input Parameters: psa, the memory address of first operand.
Input Parameters:psb, the memory address of second operand.
Output Parameters: psd, address to save results.
Output Parameters: pca, address of 32 bits unsigned integer, to save carry flag.
Input Parameters: nBytes, the legth in bytes of the integer saved in psa;
******************************************************************************/
LX_RESULT
large_int_add_c32( BYTE* psa,BYTE* psb,BYTE* psd,DWORD* pca,int nBytes )
{
int i;
DWORD dwA;
DWORD dwB;
DWORD dwC = 0;
DWORD* pwa = (DWORD*)psa;
DWORD* pwb = (DWORD*)psb;
DWORD* pwd = (DWORD*)psd;
for( i = 0; i < nBytes ; i += 4 ) {
ULARGE_INTEGER uld;
dwA = *pwa++; // 取第一个操作数 DWORD;
dwB = *pwb++; // 取第二个操作数 DWORD;
uld.QuadPart = (__int64)dwA + dwB + dwC; // 带进位加;
*pwd++ = (DWORD)( uld.LowPart); // 低 32 位输出;
dwC = (DWORD)(uld.HighPart); // 高 32 位为进位;
}
评论5