zoukankan      html  css  js  c++  java
  • 用Android NDK编译FFmpeg

    Android内置的编解码器实在太少,于是我们需要FFmpeg。Android提供了NDK,为我们使用FFmpeg这种C语言代码提供了方便。

    不过为了用NDK编译FFmpeg,还真的花费了不少时间,也得到了很多人的帮助,最应该谢谢havlenapetr。我觉得我现在这些方法算是比较简洁的了--

    下面就尽量詳細的说一下我是怎么在项目中使用FFmpeg的,但是基于我混乱的表达能力,有不明白的就问我。

    你得了解JNI和Android NDK的基本用法,若觉得我的文章还不错,可以看之前写的JNI简单入门Android NDK入门


    首先创建一个标准的Android项目vPlayer

    android create project -n vPlayer -t 8 -p vPlayer -k me.abitno.vplayer -a PlayerView
    

    然后在vPlayer目录里

    mkdir jni && cd jni
    wget http://ffmpeg.org/releases/ffmpeg-0.6.tar.bz2
    tar xf ffmpeg-0.6.tar.bz2 && mv ffmpeg-0.6 ffmpeg && cd ffmpeg
    

    在ffmpeg下新建一个config.sh,内容如下,注意把PREBUILT和PLATFORM设置正确。另外里面有些参数你也可以自行调整,我主要是为了配置一个播放器而这样设置的。

    #!/bin/bash
    
    PREBUILT=/home/abitno/Android/android-ndk-r4/build/prebuilt/linux-x86/arm-eabi-4.4.0
    PLATFORM=/home/abitno/Android/android-ndk-r4/build/platforms/android-8/arch-arm
    
    ./configure --target-os=linux \
    	--arch=arm \
    	--enable-version3 \
    	--enable-gpl \
    	--enable-nonfree \
    	--disable-stripping \
    	--disable-ffmpeg \
    	--disable-ffplay \
    	--disable-ffserver \
    	--disable-ffprobe \
    	--disable-encoders \
    	--disable-muxers \
    	--disable-devices \
    	--disable-protocols \
    	--enable-protocol=file \
    	--enable-avfilter \
    	--disable-network \
    	--disable-mpegaudio-hp \
    	--disable-avdevice \
    	--enable-cross-compile \
    	--cc=$PREBUILT/bin/arm-eabi-gcc \
    	--cross-prefix=$PREBUILT/bin/arm-eabi- \
    	--nm=$PREBUILT/bin/arm-eabi-nm \
    	--extra-cflags="-fPIC -DANDROID" \
    	--disable-asm \
    	--enable-neon \
    	--enable-armv5te \
    	--extra-ldflags="-Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtbegin.o $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtend.o -lc -lm -ldl"
    

    运行config.sh开始configure

    chmod +x config.sh
    ./config.sh
    

    configure完成后,编辑刚刚生成的config.h,找到这句

    #define restrict restrict
    

    Android的GCC不支持restrict关键字,于是修改成下面这样

    #define restrict
    

    编辑libavutil/libm.h,把其中的static方法都删除。

    分别修改libavcodec、libavfilter、libavformat、libavutil、libpostproc和libswscale下的Makefile,把下面两句删除

    include $(SUBDIR)../subdir.mak
    include $(SUBDIR)../config.mak
    

    在ffmpeg下添加一个文件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))
    

    接下来要添加一系列的Android.mk,在jni根目录下的内容如下

    include $(all-subdir-makefiles)
    

    在ffmpeg目录下,Android.mk

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale
    LOCAL_MODULE := ffmpeg
    include $(BUILD_SHARED_LIBRARY)
    include $(call all-makefiles-under,$(LOCAL_PATH))
    

    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)
    

    libavcodec/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_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)
    

    最外层的jni/Android.mk和jni/ffmpeg/Android.mk我只是随便这样写的,你应该根据自己的需求改写。

    最后运行ndk-build,经过漫长的等待就编译完成了。至于具体怎么应用可能以后会写,我变得太懒了。。。


    我已经尽最大努力写明白了,希望大家努力啊,一个全功能的解码器或者只是播放器还是很有必要的。

    更新:想偷情的可以看这个在Android NDK中使用libffmpeg.so

  • 相关阅读:
    4 Python+Selenium的元素定位方法(link/partial link)
    3 Python+Selenium的元素定位方法(id、class name、name、tag name)
    2 Selenium3.0+Python3.6环境搭建
    1 Selenium打开浏览器
    目录处理文件&链接命令
    DOS批处理命令-@命令
    DOS批处理命令-echo
    吐槽一二三
    编码神器之sublime(插件安装)
    两天来学习C的感受
  • 原文地址:https://www.cnblogs.com/qq78292959/p/2076982.html
Copyright © 2011-2022 走看看