设为首页收藏本站

数字电视开发论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

快捷登录

胜天工科技销售各种数字电视信号调制卡胜天工科技销售各种数字电视信号码流卡

【游客、新手、注册会员的区别】 【积分策略和会员晋级说明】 【发帖和附件上传规则】 【如何下载感兴趣的资料】 【如何获取梦游币】 【侵权资料处理及免责说明】
查看: 1355|回复: 0

ffmpeg不同版本的NDK编译

[复制链接]
  • TA的每日心情
    难过
    昨天 10:02
  • 签到天数: 1974 天

    [LV.Master]伴坛终老

    新浪微博达人勋

    发表于 2014-7-14 17:54:07 | 显示全部楼层 |阅读模式
    分享到:
    消息来自- 北京海淀
    0. 版本确定:

    最近需要以NativeC方式编译OpenCV2.0.  其中用到ffmpeg. (OpenCV 目录树下,有interfaces/ffopencv). 但ffmpeg版本一直在升级,在不同的版本中,接口也有所变化,如何判断OpenCV2.0使用的哪个版本的ffmpeg是个关键。

    首先观察interfaces/ffopencv/ffopencv.cpp. 其中包含:
    #ifdef WIN32
      #include   //ffmpeg_/avformat.h
      #include  //ffmpeg_/avcodec.h
      #include  //ffmpeg_/imgconvert.h
    #else
    说明Windows编译时使用这几个ffmpeg头文件。

    打开:3rdparty/include/ffmpeg_/avcodec.h
    有如下代码:
    #define LIBAVCODEC_VERSION_MAJOR 52
    #define LIBAVCODEC_VERSION_MINOR 20
    #define LIBAVCODEC_VERSION_MICRO  0

    所以,确认应该找对应的ffmpeg 版本。

    在ffmpeg官网(http://ffmpeg.org/) 分别下载了:
    ffmpeg-2.2.4.tar.gz(当前最新版本)
    ffmpeg-1.0.9.tar.gz,ffmpeg-0.6.7.tar.gz,ffmpeg-0.5.13.tar.gz
    分别打开其avcodec.h,结果0.5.13最为接近:
    #define LIBAVCODEC_VERSION_MAJOR 52
    #define LIBAVCODEC_VERSION_MINOR 20
    #define LIBAVCODEC_VERSION_MICRO  1

    所以说明:OpenCV2.0所使用的FFMpeg库是0.5.13.

    1. 开始编译:

    以下编译方法,是借鉴网络上已有的ffmpeg NDK编译之方法。只是针对各个特定ffmpeg版本做了一点微调。在此感谢分享这些编译经历的朋友。

    1.1:目录建立:
    创建jni目录。将ffmpeg-0.5.13.tar.gz copy到其中并解压缩。
    最终目录结构如下:
    jni/ffmpeg-0.5.13

    1.2: 建立config_android.sh并生成config.h文件:
    在编译X86 Linux环境下ffmpeg, 是通过configure来创建config.h 和config.mk.
    决定编译哪些模块,以及程序中用到的一些宏定义(关系到程序向哪方向走)。

    我们也需要一个config.h.  所以要利用configure来生成它。

    在jni/ffmpeg-0.5.13/目录内,创建config_android.sh
    内容如下:
    NDK_ROOT=/opt/android-ndk-r9d
    PREBUILT=${NDK_ROOT}/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
    PLATFORM=${NDK_ROOT}/platforms/android-8/arch-arm
    ./configure --target-os=linux \
    --arch=arm \
    --enable-small \
    --enable-static \
    --disable-yasm \
    --enable-armv5te \
    --enable-cross-compile \
    --disable-debug \
    --disable-stripping \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffserver \
    --disable-encoders \
    --disable-muxers \
    --disable-devices \
    --disable-bsfs \
    --disable-protocols \
    --disable-devices \
    --disable-shared \
    --disable-filters \
    --disable-postproc \
    --enable-swscale \
    --cc=$PREBUILT/bin/arm-linux-androideabi-gcc \
    --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
    --nm=$PREBUILT/bin/arm-linux-androideabi-nm \
    --extra-cflags="-fPIC -DANDROID" \
    --extra-ldflags='-L$PLATFORM/usr/lib -nostdlib' \


    echo "#undef restrict" >> config.h
    echo "#define restrict __restrict__" >> config.h
    echo "#undef HAVE_LRINT" >> config.h
    echo "#define HAVE_LRINT 1" >> config.h
    echo "#undef HAVE_LRINTF" >> config.h
    echo "#define HAVE_LRINTF 1" >> config.h
    echo "#undef HAVE_ROUND" >> config.h
    echo "#define HAVE_ROUND 1" >> config.h
    echo "#undef HAVE_ROUNDF" >> config.h
    echo "#define HAVE_ROUNDF 1" >> config.h
    echo "#undef HAVE_TRUNCF" >> config.h
    echo "#define HAVE_TRUNCF 1" >> config.h

    注意:NDK_ROOT,PREBUILT 要按照本机实际地址配置。

    之后修改其权限:
    chmod 777 config_android.sh

    运行:
    ./config_android.sh

    生成了config.h

    1.3: 微调config.h和几个文件:
    1.3.1: config.h微调:
    在config.h中,找到:
    #define restrict restrict
    #define restrict  __restrict__

    修改为:
    #define restrict
    #define restrict

    因为restrict关键字是C99才引入的。

    1.3.2:libavutil/internal.h微调:
    #if 0
    static av_always_inline av_const long long llrint(double x)
    {
        return rint(x);
    }
    #endif
    如果不去掉,llrint会重定义。(llrint是C函数)

    1.3.3:libavcodec/utils.c微调:
    fd = open(*filename, O_RDWR | O_BINARY | O_CREAT, 0444);
    修改为:
    fd = open(*filename, O_RDWR | O_CREAT, 0444);

    1.3.4: libavformat/rtsp.c微调:
    增加:
    #include    // sys/time.h
    #include   // sys/types.h
    #include      // unistd.h


    1.4: 修改Makefile:
    分别修改libavcodec、libavfilter、libavformat、libavutil、libpostproc和libswscale下的Makefile,把每个Makefile中的下面两句删除或注释掉
    include $(SUBDIR)../config.mak
    include $(SRC_PATH)/subdir.mak


    1.5:增加av.mk文件:
    在jni/ffmpeg-0.5.13中增加av.mk文件,内容如下:

    # LOCAL_PATH is one of libavutil, libavcodec, libavformat, or libswscale

    #include $(LOCAL_PATH)/../config-$(TARGET_ARCH).mak
    include $(LOCAL_PATH)/../config.mak

    OBJS :=
    OBJS-yes :=
    MMX-OBJS-yes :=
    include $(LOCAL_PATH)/Makefile

    # collect objects
    OBJS-$(HAVE_MMX) += $(MMX-OBJS-yes)
    OBJS += $(OBJS-yes)

    FFNAME := lib$(NAME)
    FFLIBS := $(foreach,NAME,$(FFLIBS),lib$(NAME))
    FFCFLAGS  = -DHAVE_AV_CONFIG_H -Wno-sign-compare -Wno-switch -Wno-pointer-sign
    FFCFLAGS += -DTARGET_CONFIG=\"config-$(TARGET_ARCH).h\"

    ALL_S_FILES := $(wildcard $(LOCAL_PATH)/$(TARGET_ARCH)/*.S)
    ALL_S_FILES := $(addprefix $(TARGET_ARCH)/, $(notdir $(ALL_S_FILES)))

    ifneq ($(ALL_S_FILES),)
    ALL_S_OBJS := $(patsubst %.S,%.o,$(ALL_S_FILES))
    C_OBJS := $(filter-out $(ALL_S_OBJS),$(OBJS))
    S_OBJS := $(filter $(ALL_S_OBJS),$(OBJS))
    else
    C_OBJS := $(OBJS)
    S_OBJS :=
    endif

    C_FILES := $(patsubst %.o,%.c,$(C_OBJS))
    S_FILES := $(patsubst %.o,%.S,$(S_OBJS))

    FFFILES := $(sort $(S_FILES)) $(sort $(C_FILES))


    1.6:在目标目录内添加Android.mk , Application.mk
    1.6.1: 先添加Android.mk

    jni/Android.mk 内容如下:
    include $(all-subdir-makefiles)

    jni/ffmpeg-0.5.13/Android.mk 内容如下:
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_STATIC_LIBRARIES := libavcodec libavformat libavutil libpostproc libswscale
    LOCAL_MODULE := ffmpeg
    include $(BUILD_SHARED_LIBRARY)
    include $(call all-makefiles-under,$(LOCAL_PATH))

    注意:为了编译一个测试程序:ffmpeg. 可以将这个Android.mk修改为如下版本:
    LOCAL_PATH := $(call my-dir)
    L_PATH := $(PWD)
    include $(CLEAR_VARS)
    LOCAL_STATIC_LIBRARIES := libavcodec libavformat libavutil libpostproc libswscale
    LOCAL_MODULE := ffmpeg
    include $(BUILD_SHARED_LIBRARY)
    include $(call all-makefiles-under,$(LOCAL_PATH))

    LOCAL_PATH := $(L_PATH)
    include $(CLEAR_VARS)
    LOCAL_ARM_MODE := arm
    LOCAL_CXXFLAGS := -D_GLIBCXX_USE_WCHAR_T -I../ -I./
    LOCAL_MODULE := ffmpeg_g
    LOCAL_SRC_FILES := ffmpeg.c cmdutils.c
    LOCAL_LDLIBS := -llog -L../../obj/local/armeabi-v7a/ -lavformat -lavcodec -lavutil -lswscale -lpostproc -lffmpeg
    include $(BUILD_EXECUTABLE)


    jni/ffmpeg-0.5.13/libavcodec/Android.mk内容如下:
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)

    ARCH=arm
    ARCH_ARM=yes

    include $(LOCAL_PATH)/../av.mk
    LOCAL_SRC_FILES := $(FFFILES)
    LOCAL_C_INCLUDES :=        \
        $(LOCAL_PATH)        \
        $(LOCAL_PATH)/..
    LOCAL_CFLAGS += $(FFCFLAGS) -Wa,-mimplicit-it=thumb
    LOCAL_LDLIBS := -lz
    LOCAL_STATIC_LIBRARIES := $(FFLIBS)
    LOCAL_MODULE := $(FFNAME)
    include $(BUILD_STATIC_LIBRARY)

    请注意:一定要添加:-Wa, -mimplicit-it=thumb
    否则会报错:
    /tmp/ccYZnT0I.s: Assembler messages:
    /tmp/ccYZnT0I.s:3268: Error: thumb conditional instruction should be in IT block -- `movgt fp,r3'
    /tmp/ccYZnT0I.s:3269: Error: thumb conditional instruction should be in IT block -- `movgt r3,sl'
    /tmp/ccYZnT0I.s:3271: Error: thumb conditional instruction should be in IT block -- `movle r3,lr'
    /tmp/ccYZnT0I.s:3273: Error: thumb conditional instruction should be in IT block -- `movgt fp,r3'


    jni/ffmpeg-0.5.13/libavformat/Android.mk 内容如下:
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    include $(LOCAL_PATH)/../av.mk
    LOCAL_SRC_FILES := $(FFFILES)
    LOCAL_C_INCLUDES :=        \
        $(LOCAL_PATH)        \
        $(LOCAL_PATH)/..
    LOCAL_CFLAGS += $(FFCFLAGS)
    LOCAL_CFLAGS += -include "string.h" -Dipv6mr_interface=ipv6mr_ifindex
    LOCAL_LDLIBS := -lz
    LOCAL_STATIC_LIBRARIES := $(FFLIBS)
    LOCAL_MODULE := $(FFNAME)
    include $(BUILD_STATIC_LIBRARY)


    libavfilter、libavutil、libpostproc和libswscale下的Android.mk内容如下:
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    include $(LOCAL_PATH)/../av.mk
    LOCAL_SRC_FILES := $(FFFILES)
    LOCAL_C_INCLUDES :=        \
        $(LOCAL_PATH)        \
        $(LOCAL_PATH)/..
    LOCAL_CFLAGS += $(FFCFLAGS)
    LOCAL_STATIC_LIBRARIES := $(FFLIBS)
    LOCAL_MODULE := $(FFNAME)
    include $(BUILD_STATIC_LIBRARY)


    1.6.2: 添加Application.mk
    所有对应的Application.mk可以自定义,Sam常用的是:
    # Build both ARMv5TE and ARMv7-A machine code.
    APP_PLATFORM = android-8

    APP_ABI := armeabi-v7a
    #APP_ABI := $(ARM_ARCH)

    #Sam modify it to release
    APP_OPTIM := release
    #APP_OPTIM := debug
    #APP_OPTIM = $(MY_OPTIM)

    APP_CPPFLAGS += -fexceptions
    APP_CPPFLAGS += -frtti

    #sam modify it from gnustl_static to gnustl_shared
    #APP_STL := gnustl_static
    #APP_STL        := gnustl_shared
    APP_STL := gnustl_shared

    #APP_CPPFLAGS += -fno-rtti

    #
    APP_CPPFLAGS += -Dlinux -fsigned-char
    APP_CFLAGS += -fsigned-char
    #APP_CPPFLAGS += $(MY_CPPFLAGS) -Dlinux
    #STLPORT_FORCE_REBUILD := true


    1.7: 编译:
    在jni目录:
    ndk-build -B V=1

    编译结果可以在jni同级目录obj下看到编译出的结果:
    obj/local/armeabi-v7a

    1.8: 编译ffmpeg 应用程序:
    如果上面在jni/ffmpeg-0.5.13目录下的Android.mk用的是第二项。则可以生成一个ffmpeg测试程序。
    则在jni/ffmpeg-0.5.13/下,
    运行:ndk-build -B V=1
    则在jni/ffmpeg-0.5.13/下生成ffmpeg应用程序。

    中间会需要version.h
    可以创建之:内容如下:
    #define FFMPEG_VERSION "0.5.13"

    1.9: 测试:
    将一段视频源转换为DVD格式:

    ./ffmpeg -i command_6.wmv -target pal-dvd -ps 2000000000 -aspect 16:9 a.mpeg

    转换后一切正常。
    踩过的脚印
    您需要登录后才可以回帖 登录 | 注册 新浪微博登陆

    本版积分规则

    嗨!您好:
    欢迎来到数字电视开发论坛。
    我的名字叫梦梦
    很高兴能够为您服务!
    如果已经注册【立即登录】
    还没有账号请【注册】
    嗨!您好:
    欢迎来到数字电视开发论坛。
    我的名字叫梦梦
    很高兴能够为您服务!
    如果已经注册【立即登录】
    还没有账号请

    QQ|小黑屋|手机版|Archiver|数字电视开发网 ( 京ICP备16008897号-5   

    GMT+8, 2018-1-21 14:56 , Processed in 0.245259 second(s), 37 queries , Gzip On.

    Powered by Discuz! X3.1

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表