在上一章,我们用最简单的tutorial01.c来编译了ffmpeg源码,并且可以用gdb追踪,这一章,我们先形成一个简单的Makefile, 以利用ffmpeg编好的本地库,而不是安装到系统的系统库,这样我们每次修改完ffmpeg的时候,只要make一下就可以了,不需要install。
我们先看一下原来的编译命令:
gcc -g -o tu ./src/tutorial01.c -lavutil -lavformat -lavcodec -lz -lavutil -lpthread -lswscale -lm -I../ffmpeg
STEP 1. 我们先写一个比较简单的Makefile
.PHONY:all all:tu tu:obj/tutorial01.o gcc -Wall -I../ffmpeg tutorial01.o -o tu -lavutil -lavformat -lavcodec -lz -lavutil -lpthread -lswscale -lm obj/tutorial01.o: src/tutorial01.c gcc -g -c src/tutorial01.c -o obj/tutorial01.o -I../ffmpeg/
STEP 2. 把gcc, include头文件的目录,库等编译参数用参数来替换,添加伪目标clean, Makefile如下:
##libs LIBS := -lavutil -lavformat -lavcodec -lz -lavutil -lpthread -lswscale -lm # ##include INCLUDE_PATH := -I../ffmpeg # #compile para CC = gcc CFLAGS = -Wall -g -c LINK = gcc .PHONY:all all:tu tu:obj/tutorial01.o $(LINK) tutorial01.o -o tu $(INCLUDE_PATH) $(LIBS) obj/tutorial01.o: src/tutorial01.c $(CC) $(CFLAGS) -c src/tutorial01.c -o obj/tutorial01.o $(INCLUDE_PATH) .PHONY:clean clean: rm -rf obj/*.o rm tu
STEP 3. 为了能之后自动检测src里所有.c的文件,我们增加了自动寻找src里.c的功能和自动通过匹配文件名生成对应的.o并放在obj目录先,然后通过链接这些.o来生成最终可执行的文件。Makefile修改及注释如下:
#find all .c file in src SRC_DIR := src SRC_FILE_TYPE = c FIND_SRC_FILES = $(shell find $(SRC_DIR) -name "*.$(SRC_FILE_TYPE)") SRC_FILES = $(notdir $(FIND_SRC_FILES) ) //选找所有src/*.c文件 #obj OBJ_FILES = $(SRC_FILES:.$(SRC_FILE_TYPE)=.o) //这里为 tutorial01.o OBJ_DIR := obj OBJS = $(addprefix $(OBJ_DIR)/,$(OBJ_FILES)) //这里为obj/tutorial01.o ##libs SYS_LIBS := -lavformat -lavcodec -lavutil -lz -lpthread -lswscale -lm #include INCLUDE_PATH := -I../ffmpeg #compile para CC = gcc CFLAGS = -Wall -g -c LINK = gcc LINK_FLAGS = -g -o target = tu .PHONY:all all:tu $(target):$(OBJS) //link所有的obj $(LINK) $(LINK_FLAGS) $@ $(OBJS) $(SYS_LIBS) $(INCLUDE_PATH) #compile source files into object files $(OBJ_DIR)/%.o: $(SRC_DIR)/%.$(SRC_FILE_TYPE) //根据.c的名字自动生成.o文件 $(CC) $(CFLAGS) $(INCLUDE_PATH) -c $< -o $@ .PHONY:clean clean: rm -rf obj/*.o rm tu .PHONY:debug //调试用 debug: @echo OBJ_FILES:$(OBJ_FILES) @echo OBJS:$(OBJS)上面的debug,是在写Makefile的过程中用于调试一些变量的,例如这里 make debug 就可以打印出OBJS的变量是不是我们需要的。
STEP 4. 因为我们后续有可能会修改ffmpeg和SDL的源码,例如添加一些打印信息等,这样我们如果用的是ffmpeg编出来的本地库,那么重编ffmpeg的时候就不用make install了,只要make就可以了,这样也可以不会影响到我们原来系统中的ffmpeg。所以,我们把ffmpeg相关的系统库(avformat, avcodec, avutil等)都改为本地库,修改Makefile相关的部分如下:
##libs LIB_DIR := ../ffmpeg LOCAL_LIBS := -L$(LIB_DIR)/libavformat -lavformat \ -L$(LIB_DIR)/libavcodec -lavcodec \ -L$(LIB_DIR)/libavutil -lavutil \ -L$(LIB_DIR)/libswscale -lswscale SYS_LIBS := -lz -lpthread -lm # ##include INCLUDE_PATH := -I../ffmpeg # #compile para CC = gcc CFLAGS = -Wall -g -c LINK = gcc LINK_FLAGS = -g -o target = tu .PHONY:all all:tu $(target):$(OBJS) $(LINK) $(LINK_FLAGS) $@ $(OBJS) $(LOCAL_LIBS) $(SYS_LIBS) $(INCLUDE_PATH)我们试着把系统里的库(/usr/local/lib/libav*.a)换个位置, 编译通过,把ffmpeg下对应的.a换个地方,编译不通过,证明用的是ffmpeg下的lib.
STEP 5. 我们用gdb进行调试,如下:
$ gdb --args ./tu test_stream/ShaoNvShiDai_720P.avi GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2 Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/liaowm/workspace/iPlayer/jni/simulation/tu...done. (gdb) b main Breakpoint 1 at 0x433d76: file src/tutorial01.c, line 77. (gdb) r Starting program: /home/liaowm/workspace/iPlayer/jni/simulation/tu test_stream/ShaoNvShiDai_720P.avi [Thread debugging using libthread_db enabled] Breakpoint 1, main (argc=2, argv=0x7fffffffe438) at src/tutorial01.c:77 77 AVFormatContext *pFormatCtx = NULL; (gdb) n 88 if(argc < 2) { (gdb) 93 av_register_all(); (gdb) 97 if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0) (gdb) s avformat_open_input (ps=0x7fffffffe310, filename=0x7fffffffe75f "test_stream/ShaoNvShiDai_720P.avi", fmt=0x0, options=0x0) at libavformat/utils.c:588 588 { (gdb) n 589 AVFormatContext *s = *ps; (gdb)可以得知可以进入avformat_open_input等ffmpeg的内部函数进行调试,目前的需求完成。到此,我们完成了ffmpeg的Makefile,为我们添加SDL的库提供了方便。下面,我们下载tutorial02.c,来进行ffmpeg和SDL的源码联合编译。