我们知道,ffmpeg源码是在linux底下开发出来的,而如果我们要在windows底下进行ffmpeg相关代码的修改和优化的话,则是需要借助mingw,mingw中提供了msys编译环境,这样的话,你修改和优化后的ffmpeg代码如果要在windows下应用的话,则可以通过编译生成相关的dll和lib库进行引用,达到最大化利用ffmpeg性能的目的。
接下来,以自己近期做的prores编解码器代码修改优化部分过程为例,来说明下如何在windows平台上通过重写makefile文件,重新编译生成新的prores编解码库。有的人可能会问,为什么不直接在vs2013平台上进行修改并编译好库,这样不也可以编译得到相应的dll和lib库吗?当然是可以的,不过由于visual studio平台在编译ffmpeg部分代码过程中并不支持部分编译选项,比如AT&T汇编优化,因此在visual studio平台上编译出的库也就不支持AT&T汇编优化,从而影响了ffmpeg进行相关流媒体处理的性能。那可能又有一部分人会问,那你直接在linux上进行开发不就行了么?当然也是可以的,只是笔者习惯了在windows下进行开发,虽说笔者电脑上也装了一个linux的虚拟机,不过老是切来切去的也不方便,所以干脆就直接在mingw上倒腾了,反正功能和linux基本一样。
好了,接下来开始上干货了。。。
1、 先上ffmpeg官网下载ffmpeg源码,分别在library.mak和common.mak的图1和图2位置处增加这两条语句:echo-e "$(YASM) $(YASMFLAGS) -I $(
图1
图2
图3
接下来保存好ffmpeg一级目录下的config.h以及config.asm两个文件,将32位和64位下分别编译得到的这两个config文件分别保存到config_x86和config_x64中。
2、 在vs2013中,新建两个工程,这里我自己命名为BaseLib和 ProResCodec,将步骤一后得到的ffmpeg重新make clean一下,然后将ffmpeg中的libavutil和libavcodec两个源码文件夹复制到自己的vs工程目录下,并在两个工程属性中,将libavutil和libavcodec中头文件全部包含进去。接下来重新利用vs编译器和msys一起编译ffmpeg,此时32位的configure选项为:./configure –enable-shared –toolchain=msvc, 64位的configure选项为:./configure–arch=x86-64 –enable-shared –toolchain=msvc,重新编译后,可得到新的config.h和config.asm,将32位和64位下分别编译得到的这两个config文件分别保存到config_x86和config_x64中,将这两个文件夹也复制到vs工程目录下,并根据不同的vs平台包含进项目BaseLib和ProResCodec中去。将proresdec2.c文档加入到ProResCodec工程,编译链接,发现有些函数没有定义或者链接不了,肯定还需要其他.c文件加入进来,根据函数名在libavutil和libavcodec文件夹中查找,逐个将相应的.c文件加入,直至最后两个工程项目都可以完全编译链接通过。
这一步主要是为了下一步进行makefile编写时需要哪些文件加入mingw编译提供参考。
3、 参考网络资料《跟我一起学makefile》(http://blog.csdn.net/haoel/article/details/2886/)资料,熟悉makefile书写规则和一般技巧。重新建立新的文件夹,将第一步中得到的config_x86和config_x64文件夹复制到新的文件夹目录下,且将ffmpeg中的源码文件夹libavutil和libavcodec复制到新的文件夹目录下,分别在两个文件夹中新建makefile文档,根据步骤二中的两个项目BaseLib和ProResCodec下分别包含的.c文件分别书写libavutil和libavcodec中的两个makefile文件,其中我自己32位的两个makefile文件参考如下:
Libavutil中makefile:
vpath %.c ../compat/msvcrt:../compat:x86 vpath %.h ../config:../:../compat/msvcrt:x86 define_macro = -D_ISOC99_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO=1 \ -D__printf__=__gnu_printf__ -DHAVE_AV_CONFIG_H -std=c99 -fomit-frame-pointer -I/mingw/include/SDL -D_GNU_SOURCE=1 \ -Dmain=SDL_main -g -Wdeclaration-after-statement -Wall -Wdisabled-optimization -Wpointer-arith -Wredundant-decls \ -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -Wno-parentheses \ -Wno-switch -Wno-format-zero-length -Wno-pointer-sign -O3 -fno-math-errno -fno-signed-zeros -fno-tree-vectorize \ -Werror=return-type -Werror=vla -Wno-maybe-uninitialized -MMD \ objectlist = avstring.o \ bprint.o \ buffer.o \ channel_layout.o \ cpu.o \ dict.o \ error.o \ eval.o \ fifo.o \ file_open.o \ frame.o \ imgutils.o \ intmath.o \ log.o \ log2_tab.o \ mathematics.o \ mem.o \ opt.o \ parseutils.o \ pixdesc.o \ random_seed.o \ rational.o \ samplefmt.o \ sha.o \ snprintf.o \ strtod.o \ time.o \ utils.o \ x86/cpu.o \ x86/cpuid.o \ x86/emms.o \ #x86/float_dsp.o \ #x86/float_dsp_init.o \ #x86/lls.o \ #x86/lls_init.o \ #x86/x86inc.o \ #x86/x86util.o dll : $(objectlist) gcc -shared -o BaseLib.dll $(objectlist) -Wl,--out-implib,BaseLib.a -O3 def : $(objectlist) dlltool -z BaseLib.def --export-all-symbols $(objectlist) lib : $(objectlist) dlltool -k --dllname BaseLib.dll --output-lib BaseLib.lib --def BaseLib.def avstring.o : avstring.c gcc -c avstring.c -I../config -I.. $(define_macro) bprint.o : bprint.c gcc -c bprint.c -I../config -I../ $(define_macro) buffer.o : buffer.c gcc -c buffer.c -I../config -I../ $(define_macro) channel_layout.o : channel_layout.c gcc -c channel_layout.c -I../config -I../ $(define_macro) cpu.o : cpu.c gcc -c cpu.c -I../config -I../ $(define_macro) dict.o : dict.c gcc -c dict.c -I../config -I../ $(define_macro) error.o : error.c gcc -c error.c -I../config -I../ $(define_macro) eval.o : eval.c gcc -c eval.c -I../config -I../ $(define_macro) fifo.o : fifo.c gcc -c fifo.c -I../config -I../ $(define_macro) file_open.o : file_open.c gcc -c file_open.c -I../config -I../ $(define_macro) frame.o : frame.c gcc -c frame.c -I../config -I../ $(define_macro) imgutils.o : imgutils.c gcc -c imgutils.c -I../config -I../ $(define_macro) intmath.o : intmath.c gcc -c intmath.c -I../config -I../ $(define_macro) log.o : log.c gcc -c log.c -I../config -I../ $(define_macro) log2_tab.o : log2_tab.c gcc -c log2_tab.c -I../config -I../ $(define_macro) mathematics.o : mathematics.c gcc -c mathematics.c -I../config -I../ $(define_macro) mem.o : mem.c gcc -c mem.c -I../config -I../ $(define_macro) opt.o : opt.c gcc -c opt.c -I../config -I../ $(define_macro) parseutils.o : parseutils.c gcc -c parseutils.c -I../config -I../ $(define_macro) pixdesc.o : pixdesc.c gcc -c pixdesc.c -I../config -I../ $(define_macro) random_seed.o : random_seed.c internal.h gcc -c random_seed.c -I../config -I../ $(define_macro) rational.o : rational.c gcc -c rational.c -I../config -I../ $(define_macro) samplefmt.o : samplefmt.c gcc -c samplefmt.c -I../config -I../ $(define_macro) sha.o : sha.c gcc -c sha.c -I../config -I../ $(define_macro) snprintf.o : snprintf.c gcc -c snprintf.c -o snprintf.o -I../ $(define_macro) strtod.o : strtod.c gcc -c strtod.c -o strtod.o -I../ $(define_macro) time.o : time.c gcc -c time.c -I../config -I../ $(define_macro) utils.o : utils.c gcc -c utils.c -I../config -I../ $(define_macro) x86/cpu.o : x86/cpu.c gcc -o x86/cpu.o -c x86/cpu.c -I../ -I../config $(define_macro) x86/cpuid.o : x86/cpuid.asm yasm -o x86/cpuid.o x86/cpuid.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/emms.o : x86/emms.asm yasm -o x86/emms.o x86/emms.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 #x86/float_dsp.o : x86/float_dsp.asm #yasm -o x86/float_dsp.o x86/float_dsp.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 #x86/float_dsp_init.o : x86/float_dsp_init.c #gcc -std=c99 -o x86/float_dsp_init.o -c x86/float_dsp_init.c -I../ -I../config -O3 #x86/lls.o : x86/lls.asm #yasm -o x86/lls.o x86/lls.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 #x86/lls_init.o : x86/lls_init.c #gcc -o x86/lls_init.o -c x86/lls_init.c -I../ -I../config -O3 #x86/x86inc.o : x86/x86inc.asm #yasm -o x86/x86inc.o x86/x86inc.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 #x86/x86util.o : x86/x86util.asm #yasm -o x86/x86util.o x86/x86util.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 .PHONY : ALL all : dll def lib clean : -rm BaseLib.dll BaseLib.a BaseLib.def BaseLib.lib *.o *.d x86/*.o x86/*.d
Libavcodec中makefile:
define_macro = -D_ISOC99_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -U__STRICT_ANSI__ -D__USE_MINGW_ANSI_STDIO=1 \ -D__printf__=__gnu_printf__ -DHAVE_AV_CONFIG_H -std=c99 -fomit-frame-pointer -I/mingw/include/SDL -D_GNU_SOURCE=1 \ -Dmain=SDL_main -g -Wdeclaration-after-statement -Wall -Wdisabled-optimization -Wpointer-arith -Wredundant-decls \ -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -Wno-parentheses \ -Wno-switch -Wno-format-zero-length -Wno-pointer-sign -O3 -fno-math-errno -fno-signed-zeros -fno-tree-vectorize \ -Werror=return-type -Werror=vla -Wno-maybe-uninitialized -MMD \ objectlist = avpacket.o \ codec_desc.o \ dsputil.o \ error_resilience.o \ faandct.o \ faanidct.o \ frame_thread_encoder.o \ h261.o \ h261data.o \ h263.o \ h264chroma.o \ h264qpel.o \ hpeldsp.o \ imgconvert.o \ jfdctfst.o \ jfdctint.o \ jrevdct.o \ mathtables.o \ mpeg4video.o \ mpegvideo.o \ mpegvideo_motion.o \ msmpeg4data.o \ options.o \ proresregister.o \ proresdata.o \ proresdec_lgpl.o \ proresdec2.o \ proresdsp.o \ proresenc_anatoliy.o \ proresenc_kostya.o \ pthread.o \ pthread_frame.o \ pthread_slice.o \ simple_idct.o \ snow.o \ snow_dwt.o \ utils.o \ videodsp.o \ wmv2.o \ wmv2dsp.o \ x86/constants.o \ x86/deinterlace.o \ x86/diracdsp_yasm.o \ x86/dsputil.o \ x86/dsputil_init.o \ x86/dsputil_mmx.o \ x86/dsputil_x86.o \ x86/dsputilenc.o \ x86/dsputilenc_mmx.o \ x86/fdct.o \ x86/fpel.o \ x86/fpel_mmx.o \ x86/h264_chromamc.o \ x86/h264_chromamc_10bit.o \ x86/h264_deblock.o \ x86/h264_deblock_10bit.o \ x86/h264_qpel.o \ x86/h264_qpel_8bit.o \ x86/h264_qpel_10bit.o \ x86/h264chroma_init.o \ x86/hpeldsp.o \ x86/hpeldsp_init.o \ x86/hpeldsp_mmx.o \ x86/idct_mmx_xvid.o \ x86/idct_sse2_xvid.o \ x86/motion_est.o \ x86/mpeg4qpel.o \ x86/mpegvideo.o \ x86/proresdsp_init.o \ x86/qpel.o \ x86/rnd_mmx.o \ x86/simple_idct.o \ x86/snowdsp.o \ x86/videodsp.o \ x86/videodsp_init.o \ dll : $(objectlist) gcc -shared -o ProResCodec.dll $(objectlist) -Wl,--out-implib,ProResCodec.a -L../libavutil -lBaseLib -L../lib -llibiconv-2 -O3 def : $(objectlist) dlltool -z ProResCodec.def --export-all-symbols $(objectlist) lib : $(objectlist) dlltool -k --dllname ProResCodec.dll --output-lib ProResCodec.lib --def ProResCodec.def avpacket.o : avpacket.c gcc -c avpacket.c -I../config -I../ $(define_macro) codec_desc.o : codec_desc.c gcc -c codec_desc.c -I../config -I../ $(define_macro) dsputil.o : dsputil.c dsputil.h dsputil_template.c bit_depth_template.c gcc -std=c99 -c dsputil.c -I../config -I../ $(define_macro) error_resilience.o : error_resilience.c gcc -c error_resilience.c -I../config -I../ $(define_macro) faandct.o : faandct.c gcc -c faandct.c -I../config -I../ $(define_macro) faanidct.o : faanidct.c gcc -c faanidct.c -I../config -I../ $(define_macro) frame_thread_encoder.o : frame_thread_encoder.c gcc -c frame_thread_encoder.c -I../config -I../ $(define_macro) h261.o : h261.c gcc -c h261.c -I../config -I../ $(define_macro) h261data.o : h261data.c gcc -c h261data.c -I../config -I../ $(define_macro) h263.o : h263.c gcc -c h263.c -I../config -I../ $(define_macro) h264chroma.o : h264chroma.c gcc -c h264chroma.c -I../config -I../ $(define_macro) h264qpel.o : h264qpel.c gcc -c h264qpel.c -I../config -I../ $(define_macro) hpeldsp.o : hpeldsp.c gcc -c hpeldsp.c -I../config -I../ $(define_macro) imgconvert.o : imgconvert.c gcc -c imgconvert.c -I../config -I../ $(define_macro) jfdctfst.o : jfdctfst.c gcc -c jfdctfst.c -I../config -I../ $(define_macro) jfdctint.o : jfdctint.c gcc -c jfdctint.c -I../config -I../ $(define_macro) jrevdct.o : jrevdct.c gcc -c jrevdct.c -I../config -I../ $(define_macro) mathtables.o : mathtables.c gcc -c mathtables.c -I../config -I../ $(define_macro) mpeg4video.o : mpeg4video.c gcc -c mpeg4video.c -I../config -I../ $(define_macro) mpegvideo.o : mpegvideo.c gcc -c mpegvideo.c -I../config -I../ $(define_macro) mpegvideo_motion.o : mpegvideo_motion.c gcc -c mpegvideo_motion.c -I../config -I../ $(define_macro) msmpeg4data.o : msmpeg4data.c gcc -c msmpeg4data.c -I../config -I../ $(define_macro) options.o : options.c gcc -c options.c -I../config -I../ $(define_macro) proresregister.o : proresregister.c gcc -c proresregister.c -I../config -I../ $(define_macro) proresdata.o : proresdata.c gcc -c proresdata.c -I../config -I../ $(define_macro) proresdec_lgpl.o : proresdec_lgpl.c gcc -c proresdec_lgpl.c -I../config -I../ $(define_macro) proresdec2.o : proresdec2.c gcc -c proresdec2.c -I../config -I../ $(define_macro) proresdsp.o : proresdsp.c gcc -c proresdsp.c -I../config -I../ $(define_macro) proresenc_anatoliy.o : proresenc_anatoliy.c gcc -c proresenc_anatoliy.c -I../config -I../ $(define_macro) proresenc_kostya.o : proresenc_kostya.c gcc -c proresenc_kostya.c -I../config -I../ $(define_macro) pthread.o : pthread.c gcc -c pthread.c -I../config -I../ $(define_macro) pthread_frame.o : pthread_frame.c gcc -c pthread_frame.c -I../config -I../ $(define_macro) pthread_slice.o : pthread_slice.c gcc -c pthread_slice.c -I../config -I../ $(define_macro) simple_idct.o : simple_idct.c gcc -c simple_idct.c -I../config -I../ $(define_macro) snow.o : snow.c gcc -c snow.c -I../config -I../ $(define_macro) snow_dwt.o : snow_dwt.c gcc -c snow_dwt.c -I../config -I../ $(define_macro) utils.o : utils.c gcc -std=c99 -c utils.c -I../config -I../ $(define_macro) videodsp.o : videodsp.c gcc -c videodsp.c -I../config -I../ $(define_macro) wmv2.o : wmv2.c gcc -c wmv2.c -I../config -I../ $(define_macro) wmv2dsp.o : wmv2dsp.c gcc -c wmv2dsp.c -I../config -I../ $(define_macro) x86/constants.o : x86/constants.c gcc -o x86/constants.o -c x86/constants.c -I../config -I../ -O3 x86/deinterlace.o : x86/deinterlace.asm yasm -o x86/deinterlace.o x86/deinterlace.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/diracdsp_yasm.o : x86/diracdsp_yasm.asm yasm -o x86/diracdsp_yasm.o x86/diracdsp_yasm.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/dsputil.o : x86/dsputil.asm yasm -o x86/dsputil.o x86/dsputil.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/dsputil_init.o : x86/dsputil_init.c gcc -o x86/dsputil_init.o -c x86/dsputil_init.c -I../config -I../ -O3 x86/dsputilenc.o : x86/dsputilenc.asm yasm -o x86/dsputilenc.o x86/dsputilenc.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/dsputilenc_mmx.o : x86/dsputilenc_mmx.c gcc -o x86/dsputilenc_mmx.o -c x86/dsputilenc_mmx.c -I../config -I../ -O3 x86/fpel.o : x86/fpel.asm yasm -o x86/fpel.o x86/fpel.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/fpel_mmx.o : x86/fpel_mmx.c gcc -o x86/fpel_mmx.o -c x86/fpel_mmx.c -I../config -I../ -O3 x86/h264_chromamc.o : x86/h264_chromamc.asm yasm -o x86/h264_chromamc.o x86/h264_chromamc.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/h264_chromamc_10bit.o : x86/h264_chromamc_10bit.asm yasm -o x86/h264_chromamc_10bit.o x86/h264_chromamc_10bit.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/h264_deblock.o : x86/h264_deblock.asm yasm -o x86/h264_deblock.o x86/h264_deblock.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/h264_deblock_10bit.o : x86/h264_deblock_10bit.asm yasm -o x86/h264_deblock_10bit.o x86/h264_deblock_10bit.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/h264_qpel.o : x86/h264_qpel.c gcc -o x86/h264_qpel.o -c x86/h264_qpel.c -I../config -I../ -O3 x86/h264_qpel_8bit.o : x86/h264_qpel_8bit.asm yasm -o x86/h264_qpel_8bit.o x86/h264_qpel_8bit.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/h264_qpel_10bit.o : x86/h264_qpel_10bit.asm yasm -o x86/h264_qpel_10bit.o x86/h264_qpel_10bit.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/h264chroma_init.o : x86/h264chroma_init.c gcc -o x86/h264chroma_init.o -c x86/h264chroma_init.c -I../config -I../ -O3 x86/hpeldsp.o : x86/hpeldsp.asm yasm -o x86/hpeldsp.o x86/hpeldsp.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/hpeldsp_init.o : x86/hpeldsp_init.c gcc -o x86/hpeldsp_init.o -c x86/hpeldsp_init.c -I../config -I../ -O3 x86/motion_est.o : x86/motion_est.c gcc -o x86/motion_est.o -c x86/motion_est.c -I../config -I../ -O3 x86/mpeg4qpel.o : x86/mpeg4qpel.asm yasm -o x86/mpeg4qpel.o x86/mpeg4qpel.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/mpegvideo.o : x86/mpegvideo.c gcc -o x86/mpegvideo.o -c x86/mpegvideo.c -I../config -I../ -O3 x86/proresdsp_init.o : x86/proresdsp_init.c gcc -o x86/proresdsp_init.o -c x86/proresdsp_init.c -I../config -I../ -O3 x86/qpel.o : x86/qpel.asm yasm -o x86/qpel.o x86/qpel.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/snowdsp.o : x86/snowdsp.c gcc -o x86/snowdsp.o -c x86/snowdsp.c -I../config -I../ -O3 x86/videodsp.o : x86/videodsp.asm yasm -o x86/videodsp.o x86/videodsp.asm -I../config -P config.asm -I../ -f win32 -DPREFIX -O3 x86/videodsp_init.o : x86/videodsp_init.c gcc -o x86/videodsp_init.o -c x86/videodsp_init.c -I../config -I../ -O3 x86/dsputil_mmx.o : x86/dsputil_mmx.c gcc -o x86/dsputil_mmx.o -c x86/dsputil_mmx.c -I../config -I../ -O3 x86/idct_mmx_xvid.o : x86/idct_mmx_xvid.c gcc -o x86/idct_mmx_xvid.o -c x86/idct_mmx_xvid.c -I../config -I../ -O3 x86/idct_sse2_xvid.o : x86/idct_sse2_xvid.c gcc -o x86/idct_sse2_xvid.o -c x86/idct_sse2_xvid.c -I../config -I../ -O3 x86/simple_idct.o : x86/simple_idct.c gcc -o x86/simple_idct.o -c x86/simple_idct.c -I../config -I../ -O3 x86/fdct.o : x86/fdct.c gcc -o x86/fdct.o -c x86/fdct.c -I../config -I../ -O3 x86/hpeldsp_mmx.o : x86/hpeldsp_mmx.c gcc -o x86/hpeldsp_mmx.o -c x86/hpeldsp_mmx.c -I../config -I../ -O3 x86/dsputil_x86.o : x86/dsputil_x86.c gcc -o x86/dsputil_x86.o -c x86/dsputil_x86.c -I../config -I../ -O3 x86/rnd_mmx.o : x86/rnd_mmx.c gcc -o x86/rnd_mmx.o -c x86/rnd_mmx.c -I../config -I../ -O3 .PHONY : ALL all : dll def lib clean : -rm ProResCodec.dll ProResCodec.a ProResCodec.def ProResCodec.lib *.o *.d x86/*.o
其中define_macro就是在第一步中output.log中打印出的编译选项,而x86文件夹下的.c文件的编译选项则是在asmout.log中打印出的编译选项。
4、 最后,在libavutil和libavcodec同级目录下,再新建一个makefile文件,用于先后引导libavutil和libavcodec中的两个makefile编译,具体makefile内容如下:
MAKE := make all CLEAN := make clean INSTALLDIR := OutDll LIBDLL := libavutil/BaseLib.lib libavutil/BaseLib.dll libavcodec/ProResCodec.lib libavcodec/ProResCodec.dll all : cd libavutil && $(MAKE) cd libavcodec && $(MAKE) clean : cd libavutil && $(CLEAN) cd libavcodec && $(CLEAN) install : cp $(LIBDLL) $(INSTALLDIR) .PHONY : all clean
5、 我的各层级的目录关系如下图4:
图4