结合系列教程http://dranger.com/ffmpeg/tutorial01.html把ffmpeg,SDL和教程在linux平台下用GCC编译,并加入调试参数,已达到能编译后所有源码都能用gdb跟踪的效果。网页上有很多教程都是使用VC或者mingui的,而且用的是已经编好的ffmpeg和SDL的库来编译,这样的好处是免去了一些编译的步骤和时间,但是却不能让我们可以自己跟踪ffmpeg和SDL的源码。为了能结合跟踪这些源码,用ffmpeg和SDL的源码以及教程的调用代码来编译一个工程,这里结合我自己的操作,一步一步列出从简单到复杂的综合编译过程,也希望能在这个过程重拾对Makefile的理解。
1. 首先建立目录ffmpeg和SDL,分别下载ffmpeg和SDL(http://www.libsdl.org/download-1.2.php)的源码。在ffmpeg里运行
./configure --disable-yasm make在SDL目录里运行
./configure make
2. 建立与ffmpeg和SDL同级的目录simulation, 在simulation下建立src, include, out, obj这四个目录,并把tutorial01.c放在src目录下。具体的目录结构如下:
---ffmpeg
---SDL
---simulation
--------src
--------include
--------obj
--------Makefile
3. 由于tutorial01.c对应的ffmpeg的版本有些旧,有些宏定义和API的名字需要修改,如下:
#include "avcodec.h" ---> #include "libavcodec/avcodec.h" #include "avformat.h" ---> #include "libavformat/avformat.h" CODEC_TYPE_VIDEO ---> AVMEDIA_TYPE_VIDEO if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0) ---> if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0) dump_format(pFormatCtx, 0, argv[1], 0); ---> av_dump_format(pFormatCtx, 0, argv[1], 0); avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, packet.data, packet.size); ---> avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
gcc -g -o tu ./src/tutorial01.c -lavutil -lavformat -lavcodec -lz -lavutil -lm -I../ffmpeg出现一下编译报错信息:
tutorial01.c:(.text+0x378): undefined reference to `img_convert'这时由于新版的ffmpeg已经用swscale来取代了运来旧版的img_convert函数导致的,因此,进行下面4的修改。
4.对tutorial01.c增加一下内容
#include "libswscale/swscale.h" #include "libswscale/swscale_internal.h" int img_convert(AVPicture *dst, int dst_pix_fmt, const AVPicture *src, int src_pix_fmt, int src_width, int src_height) { int w; int h; SwsContext *pSwsCtx; w = src_width; h = src_height; pSwsCtx = sws_getContext(w, h, src_pix_fmt, w, h, dst_pix_fmt, SWS_BICUBIC, NULL, NULL, NULL); sws_scale(pSwsCtx, src->data, src->linesize, 0, h, dst->data, dst->linesize); //这里释放掉pSwsCtx的内存 return 0; }上面是用新版的API接口重写了img_convert函数。另外,由于用到了libswscale库,必须在编译命令里加 -lswscale, 用下面的命令编译:
gcc -g -o tu ./src/tutorial01.c -lavutil -lavformat -lavcodec -lz -lavutil -lswscale -lm -I../ffmpeg
编译报错:
/home/liaowm/workspace/iPlayer/jni/ffmpeg/libavformat/udp.c:657: undefined reference to `pthread_cancel' /home/liaowm/workspace/iPlayer/jni/ffmpeg/libavformat/udp.c:658: undefined reference to `pthread_join' /usr/local/lib/libavformat.a(udp.o): In function `udp_open': /home/liaowm/workspace/iPlayer/jni/ffmpeg/libavformat/udp.c:545: undefined reference to `pthread_create' /usr/local/lib/libavcodec.a(pthread.o): In function `frame_thread_free': /home/liaowm/workspace/iPlayer/jni/ffmpeg/libavcodec/pthread.c:756: undefined reference to `pthread_join' /usr/local/lib/libavcodec.a(pthread.o): In function `thread_free': /home/liaowm/workspace/iPlayer/jni/ffmpeg/libavcodec/pthread.c:251: undefined reference to `pthread_join' /usr/local/lib/libavcodec.a(pthread.o): In function `frame_thread_init': /home/liaowm/workspace/iPlayer/jni/ffmpeg/libavcodec/pthread.c:873: undefined reference to `pthread_create' /usr/local/lib/libavcodec.a(pthread.o): In function `thread_init': /home/liaowm/workspace/iPlayer/jni/ffmpeg/libavcodec/pthread.c:339: undefined reference to `pthread_create'
gcc -g -o tu ./src/tutorial01.c -lavutil -lavformat -lavcodec -lz -lavutil -lswscale -lpthread -lm -I../ffmpeg
5. 运行程序
./tu test.avi
Program received signal SIGSEGV, Segmentation fault. init_input (ps=0x7fffffffe2d0, filename=0x7fffffffe720 "/home/liaowm/workspace/iPlayer/jni/simulation/test_stream/352x240_H263_MP3_0_24_CiKeLianMeng.flv", fmt=<value optimized out>, options=0x0) at libavformat/utils.c:537 537 s->flags |= AVFMT_FLAG_CUSTOM_IO;
cd ../ffmpeg ./configure --disable-yasm --enable-static make; make install gcc -g -o tu ./src/tutorial01.c -lavutil -lavformat -lavcodec -lz -lavutil -lpthread -lswscale -lm -I../ffmpeg
再接下来的一章,我们会继续尝试用一个简单的Makefile来完善这个工程。