现在的位置: 首页 > 综合 > 正文

在linux下联合编译ffmpeg和SDL源码之一

2013年11月03日 ⁄ 综合 ⁄ 共 4242字 ⁄ 字号 评论关闭

        结合系列教程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

       生成的库libSDL.a和libSDLmain.a在SDL/build/.libs目录下。


       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'

         是由于没有链接到pthread相关的库造成的,因此,再次修改编译命令,增加 -lpthread, 如下:

gcc -g -o tu ./src/tutorial01.c -lavutil -lavformat -lavcodec -lz -lavutil -lswscale -lpthread -lm -I../ffmpeg

         编译通过。

5. 运行程序

./tu test.avi

         出现段错误报错,用gdb 调试, 发现错误报告如下:

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;

        查阅了下网络,段错误一般是由于对非法地址(超出程序空间)引起的,而这些代码应该是没有这种明显的bug的,所以有可能是由于动态库和静态库之间空间的使用差别引起的,所以,对ffmpeg添加 --enable-static参数进行重新编译和安装,再重新编译程序:

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

        再重新运行,解码正确,输出了5个RGB图片:frame1.ppm ~ frame5.ppm, 用display或其他图形工具可以看到。

 再接下来的一章,我们会继续尝试用一个简单的Makefile来完善这个工程。


抱歉!评论已关闭.