摘要: 这部分主要是引入第三方库,还有就去去除无关的测试代码。7. 引入第三方库 必须引入的第三方库为zdll.lib,这个库在网上可以下载到,如若不加入这个库,很多的函数将链接不到。还有在avcodec文件夹下面以lib打头的文件都是为引入第三方库而进行的接口封装,以适应ffmpeg去调用的相关代码。最重要的例如libx264,libmp3lame.lib libfdk_aac等。我的x264采用我自己用vs2008编译的版本,其它的库也基本上采用vs的版本。暂时不想加入的库,例如libspeex等可以把这些代码移出。8. 去除冗余和暂时不相关的代码。 之前我们把所有的c文件都添加进来,其实有些.. 阅读全文
posted @ 2013-04-23 17:34 celerychen 阅读(420) 评论(0) 推荐(0) 编辑
摘要: 5. 排除编译错误。 这部分主要是修改C99的语法,常见的不兼容语法如下:5.1 例如在文件av_codec_4xm.c最后的结构体初始化代码如下:AVCodec ff_fourxm_decoder = { .name = "4xm", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_4XM, .priv_data_size = sizeof(FourXContext), .init = decode_init, .close ... 阅读全文
posted @ 2013-04-23 16:02 celerychen 阅读(375) 评论(0) 推荐(0) 编辑
摘要: 前面我们已经把文件重命名了,准备好了代码之后就是把代码添加到vs2008开发环境中来。3. 创建工程添加文件。 创建新的空的控制台工程,把所有的文件都添加进来。有几个文件夹下面的文件不用添加,主要有compat,libavdevice,tools。要注意的是子目录x86下面的c文件也需要添加进来。 上图之中test文件夹里面有些文件是自己添加的,它们是config.h, ffmpeg_init_av_pix_fmt_descriptor.c,g_var_func_init.c 添加完文件之后,不要编译,因为编译会占用较长时间,而且会有成千上万的错误。4. 完善config.h文件 ... 阅读全文
posted @ 2013-04-23 15:29 celerychen 阅读(806) 评论(0) 推荐(0) 编辑
摘要: 做音视频编解码的人都知道ffmpeg。然而,要想在windows上调试ffmpeg却不是一件容易的事情。之前也曾经把x264的代码移植到vs2008上面,具体可以参见我前面的文章。最近终于把ffmpeg的最新代码完全移植到vs2008环境中来。在移植过程中深深的感觉到codec的多样性,我虽然在codec领域工作了很多年,但是ffmpeg里面大多数codec甚至连名字都没有见过。下面把移植过程中需要注意的问题描述一下。首先,必须要有坚强的毅力和决心。ffmpeg代码量超级大,其总共有3千多个文件,将近100w行代码。移植ffmpeg是一项体力很繁重的活,所以,如果你决定要做,就不要中途放弃。其 阅读全文
posted @ 2013-04-23 14:31 celerychen 阅读(661) 评论(0) 推荐(0) 编辑
摘要: 4. 数据移位指令 4.1 16位并行左移指令 psllw MM,MM/m64 psllw MM,imm8 把目的寄存器按字由源存储器(或imm8 立即数)指定位数逻辑左移,移出的位丢失. 低字移出的位不会移入高字. 例: 当MM0 = 0xffff ffff ffff ffff, 执行psllw MM0,1 则MM0 = 0xfffe fffe fffe fffe 4.2 16位并行逻辑右移指令 psrlw MM,MM/m64 psrlw MM,imm8 把目的寄存器按字由源存储器(或imm8 立即数)指定位数逻辑右移,移出的位丢失. 高字移出的位不会移入低字. 例: 当MM0 = 0xf. 阅读全文
posted @ 2013-04-23 12:22 celerychen 阅读(720) 评论(0) 推荐(0) 编辑
摘要: 6. 数据压缩指令 packuswb MM,MM/m64 把目的寄存器按字有符号数压缩为饱和字节无符号数放入目的寄存器低32位, 把源寄存器字有符号数压缩为饱和字节无符号数放入目的寄存器高32位。 简单的说,就是16位有符号压缩为饱和8位无符号数。 高32位 | 低32位 目的寄存器: a0 | a1 | a2 | a3 源寄存器: b0 | b1 | b2 | b3 目的寄存器压缩结果: b0|b1| b2|b3| a0|a1|a2|a3 例: 当MM0 == 0x 7fff 8000 1234 00ae, ... 阅读全文
posted @ 2013-04-23 12:22 celerychen 阅读(563) 评论(0) 推荐(1) 编辑
摘要: 经过我长达半年时间的预研与优化,我的美白磨皮算法基本上可以拿来商用了。测试图片的效果表明,我的美白磨皮的算法已经超过ios上各类图像特效软件的处理结果。先来看我用openCv做的demo:算法有4个可调的参数,用以控制细节,由于可调的参数太多,导致openCv的主窗口没法显示全部的图像。可以来看一下处理之前后的对比图像:处理之前:美白磨皮之后:再来看另外一张人脸的效果:算法处理之前:美白磨皮算法之后: 阅读全文
posted @ 2013-04-23 12:22 celerychen 阅读(454) 评论(0) 推荐(0) 编辑
摘要: MMX指令有8个64位寄存器(MM0~MM7),不过可惜都是借的FPU的, FPU原来有8个80位寄存器(st(0)~st(7)),现在用在了MMX上,所以用之后要加上一条EMMS指令,用以复位.MMX寄存器有64位,可以同时进行8对字节或4对字或2对双字同时相同操作,还可以进行饱和运算,不会溢出,当然也可以进行普通运算.特别要注意的一点是:在x86上,一个字,WORD的长度是16位,而在ARM上,一个WORD的长度是32位。描述约定: MM表示64位MMX寄存器. r32表示32位通用寄存器或esi,edi m32表示32位内存变量 m64表示64位内存变量 m128表示128位内存变量 i 阅读全文
posted @ 2013-04-23 12:22 celerychen 阅读(1776) 评论(0) 推荐(0) 编辑
摘要: SSE有8个128位独立寄存器(XMM1~XMM7),指令描述约定: MM指64位MMX寄存器 XMM指128XMM寄存器 m32 指32位内存变量 m128指128位内存变量1. 数据传送指令 movapsXMM,XMM/m128 movaps XMM/m128,XMM 把源存储器内容值送入目的寄存器,当有m128时, 内存地址必须是16字节对齐的。 movups XMM,XMM/m128 movaps XMM/m128,XMM 与movaps 执行的结果相同,但内存地址可以不是16字节对齐的,速度没有movaps 的快! movlps XMM, m64 把源存储器64位内... 阅读全文
posted @ 2013-04-23 12:22 celerychen 阅读(1687) 评论(0) 推荐(0) 编辑
摘要: 4. 数据重排指令集 unpckhps XMM,XMM/m128 源存储器与目的寄存器高64位按双字交错排列,结果送入目的寄存器,内存变量必须对齐内存16字节. 高64位 | 低64位 目的寄存器: a0 | a1 | a2 | a3 源存储器: b0 | b1 | b2 | b3 目的寄存器结果: b0 | a0 | b1 | a1 例: 当 XMM0 = 0x 0c517e000 44290000 46b6d000 3c4985f0 XMM1 = 0x 045e51000 4240cccd 4a59e540 ... 阅读全文
posted @ 2013-04-23 12:22 celerychen 阅读(1906) 评论(0) 推荐(0) 编辑
摘要: 6. SSE整数运算指令 pavgb MM,MM/m64 pavgb XMM,XMM/m128 把源存储器与目的寄存器按字节无符号整数相加,再除以2,结果四舍五入为整数放入目的寄存器。 源存储器为m128时,内存变量地址必须16字节对齐. pavgw MM,MM/m64 pavgw XMM,XMM/m128 把源存储器与目的寄存器按字无符号整数相加,再除以2,结果四舍五入为整数放入目的寄存器, 源存储器为m128时,内存变量必须对齐内存16字节. pextrw r32,MM,imm8 pextrw r32,XMM,imm8 从源寄存器中选第imm8(0~3 或 0~... 阅读全文
posted @ 2013-04-23 12:22 celerychen 阅读(797) 评论(0) 推荐(0) 编辑
摘要: 本小节描述的是SSE2整数运算指令。5. 数据搬移指令 movdqa XMM,XMM/m128 movdqa XMM/m128,XMM 把源存储器内容值送入目的寄存器,当有m128时,内存地址必须16字节对齐. movdqu XMM,XMM/m128 movdqu XMM/m128,XMM 把源存储器内容值送入目的寄存器,内存地址不必16字节对齐. movq2dq XMM,MM 把源寄存器内容送入目的寄存器的低64位,高64位清零. movdq2q MM,XMM 把源寄存器低64位内容送入目的寄存器.6. 算数运算指令 要点: 1. SSE2的算数运算指... 阅读全文
posted @ 2013-04-23 12:22 celerychen 阅读(1369) 评论(0) 推荐(0) 编辑
摘要: 实际上,搞汇编优化的很多时间是在处理如何有效的组织数据,以适应并行计算指令的数据结构。本小结描述的是数据混洗指令,这类指令使用起来相当的灵活。具体如下: 1. shufps XMM,XMM/m128,imm8(0~255) 描述: 从指令后缀来看,这是一条SSE1指令。 该指令把源存储器与目的寄存器按双字32位划分,由立即数imm8八个二进制位(00~11,00^11,00~11,00~11)指定排列, 目的寄存器高64位放源存储器被指定数,目的寄存器低64位放目的寄存器被指定数。内存变量地址必须对齐16字节 imm8的高4位选的是源存储器,低4位选的是目的... 阅读全文
posted @ 2013-04-23 12:22 celerychen 阅读(2053) 评论(0) 推荐(0) 编辑
摘要: 1. 数据加载存储指令 LDDQU xmm, m128 从非对齐的内存地址中加载128位数到XMM寄存器,此条指令比SSE2的非对齐加载指令MOVDQU 要快。 MOVDDUPxmm,xmm/m64 加载64bit数据到XMM寄存器的低64位,同时复制到其高64位。 MOVSHDUPxmm, xmm/m128 只需复制第二与第四个32位元素从而把数据读入到接收寄存器中 MOVSLDUPxmm, xmm/m128 只需复制第一和第三个32位元素从而把数据读入到接收寄存器中2. 算术指令 ADDSUBPD - (Add-Subtract-Packed-Double) 双精度浮点高位加法... 阅读全文
posted @ 2013-04-23 12:22 celerychen 阅读(302) 评论(0) 推荐(0) 编辑
摘要: 这里简要描述几个重要的算数运算指令。1. 水平相加指令 SSSE3指令集增加的主要是针对整数进行水平方向上相加的指令,与SSE3的浮点指令类似。 phaddd 寄存器水平方向上按照无符号32位整数进行加法 phaddw 寄存器水平方向上按照无符号16位整数进行加法 phaddsw 寄存器水平方向上按照16位整数进行饱和加法 phsubd 寄存器水平方向上按照无符号32位整数进行减法 phsubw 寄存器水平方向上按照无符号16位整数进行减法 phsubsw 寄存器水平方向上按照16位整数进行饱和减法 示例: phaddw Dest, SRC 源数据和目的数据水平相... 阅读全文
posted @ 2013-04-23 12:22 celerychen 阅读(891) 评论(0) 推荐(0) 编辑
摘要: 本文要谈的是这样一条指令:PSADBW这条指令是SSE1引入的用于视频编码绝对差值求和的指令。在视频编码中的运动估计模块,一种常见的SAD代码如下:1 // Get the SAD 16x16 macro block with full pixel2 for (y = 0; y < 16; y++)3 for(x = 0; x < 16; x++)4 sad += abs(current[y][x] - reference[y][x])对于这段代码,我们首先来用MMX指令做优化。1. SAD的MMX优化我们使用带饱和运算的PSUBUSB指令来实现求ABS (B - A)的功能。.. 阅读全文
posted @ 2013-04-23 12:22 celerychen 阅读(806) 评论(0) 推荐(0) 编辑
摘要: 本文要介绍的是SSE4.1指令集中的几条整数指令及其在视频编码中的应用。1.单指令32字节差分绝对值求和指令 MPSADBW 这条指令类似于SSE的PSADBW,但它实现的功能更强大。包括微软官方网站上对这条指令的说明都不是能够让人一目了然。下面这张图也许可以帮助我们理解: 这条指令的灵活之处在于源操作数和目的操作数的位置都是可选的。如何选择关键在于后面那个mask常量。这个常量是一个立即数,但只用到了其中的低三位。 其中,最低2位,用于选择源操作数的连续4个字节的起始位置。由于两位二进制有4中状态,所以源操作数的可选起始位置共有4种,具体见上图。 mask的第三位用于选择目的操... 阅读全文
posted @ 2013-04-23 12:22 celerychen 阅读(1371) 评论(0) 推荐(0) 编辑