JavaCpp之FFMPEG实战教程

作者: Young_Allen | 来源:发表于2017-12-13 10:46 被阅读182次

    1.文章介绍

    最近在业务扩展方面需要接触FFMPEG,借此机会学习点FFMPEG知识,由于大部分工作时间和Android应用层,Framework层和芯片SDK层打交道,自然而然看到JavaCpp这种能提高工作效率的框架,两眼发亮并想可以做些什么,这就是写本篇文章的缘由。
    另外,了解JavaCpp的同学应该也有不少,但我自己搜在Android上使用的相关教程却很少很少,于是就自己从零开始记录下实战作为参考。
    如网上说的做FFMPEG的人分为两种:一种是懂些皮毛,指令,却没有很好的入门学习方法的开发者;一种是熟悉FFMPEG各个模块,并且可以按照业务需求优化和扩展的大神。我只是第一种,甚至还算不上第一种。

    2.干货

    1.编译准备过程

    1.环境搭建

    Ubuntu16.04
    Ubuntu的搭建这里就不作介绍了,主要是需要配置好网络环境,Maven编译过程中会根据pom.xml中的依赖去中央仓库下载对应的依赖库,本文使用的是ubuntu-16.04-desktop-amd64.iso

    JDK环境配置
    下载如 jdk-7u45-linux-x64.tar.gz
    解压后jdk库文件后,配置jdk环境:

    vim /etc/environment 
    

    添加以下代码:

      update-alternatives --install /usr/bin/java java /usr/lib/jvm/java/jdk1.7.0_45/bin/java 300      
      update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/java/jdk1.7.0_45/bin/javac 300   
      update-alternatives --install /usr/bin/jar jar /usr/lib/jvm/java/jdk1.7.0_45/bin/jar 300    
      update-alternatives --config java
      update-alternatives --config javac
      update-alternatives --config jar
    

    或通过配置环境变量命令:

    $sudo gedit ~/.bashrc
    

    添加以下代码:

    export JAVA_HOME=/usr/lib/jvm/java/jdk1.7.0_45   
    export JRE_HOME=${JAVA_HOME}/jre  
    export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib  
    export PATH=${JAVA_HOME}/bin:$PATH
    

    通过以下指令校验jdk信息:

      java -version
    

    maven 3.0 or laster

    sudo apt-get install maven
    

    安装完后查看版本是否达到要求,如果版本比较低建议去官网下载对应版本后手动配置安装

    mvn -v
    
    maven版本信息

    cmake 2.8.8 or laster

    sudo apt-get install cmake
    

    安装完后查看版本是否达到要求,如果版本比较低建议去官网下载对应版本后手动配置安装

    cmake --version
    
    cmake版本信息

    svn安装

    sudo apt-get install subversion
    

    2.javacpp的下载和编译:

    1.我选择了tag版本,tag版本应该稳定些
    在github上找到对应tag版本地址:



    复制项目地址,然后下载对应源码:
    个人习惯问题,我使用的是svn,先去Repository svn地址:



    然后选择tag的svn地址checkout:
    svn checkout  https://github.com/bytedeco/javacpp.git/tags/1.3.3 /home/yang/share/javacpp-133
    

    源码下载成功后,就可以通过Maven编译了(前提是安装了Maven,未安装的可以根据提示sudo apt-get install maven安装),在下载代码的根目录下执行编译:

    mvn install
    

    编译成功后的target目录:



    其中:
    javacpp.jar是javacpp核心文件,可以说是java-cpp联系的桥梁,处理jar到so的接口实现
    javacpp-javadoc.jar是javacpp api doc文件
    javacpp-source.jar是对src目录的编译文件暂时不清楚用途

    3.javacpp-ffmpeg的下载和编译:

    javacpp-ffmpeg的源码在javacpp-presets下:
    https://github.com/bytedeco/javacpp-presets


    同样的也是选择了tag版本,使用svn下载代码:
    svn checkout  https://github.com/bytedeco/javacpp-presets.git/tags/1.3 /home/yang/share/javacpp-presets-13
    

    如果选择的是Android版本的编译,需要先准备NDK环境,否则编译过程中会因为找不到NDK配置而导致中断:
    从javacpp_presets根目录的cppbuild.sh中可以看到以下源码

    if [[ -z ${OPERATION:-} ]]; then
        echo "Usage: ANDROID_NDK=/path/to/android-ndk/ bash cppbuild.sh [-platform <name>] <install | clean> [projects]"
        echo "where possible platform names are: android-arm, android-x86, linux-x86, linux-x86_64, macosx-x86_64, windows-x86, windows-x86_64, etc."
        exit 1
    fi
    
    if [[ -z ${ANDROID_NDK:-} ]]; then
        ANDROID_NDK=~/Android/android-ndk/
    fi
    export ANDROID_NDK
    export ANDROID_CPP="$ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/4.9/"
    case $PLATFORM in
        android-x86)
            export ANDROID_BIN="$ANDROID_NDK/toolchains/x86-4.9/prebuilt/$KERNEL-$ARCH/bin/i686-linux-android"
            export ANDROID_ROOT="$ANDROID_NDK/platforms/android-14/arch-x86/"
            ;;
        *)
            export ANDROID_BIN="$ANDROID_NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/$KERNEL-$ARCH/bin/arm-linux-androideabi"
            export ANDROID_ROOT="$ANDROID_NDK/platforms/android-14/arch-arm/"
            ;;
    esac
    

    而从javacpp_presets根目录的pom.xml中可以看到这样的源码:

    <profile>
          <id>android-arm-default</id>
          <activation>
            <property>
              <name>javacpp.platform</name>
              <value>android-arm</value>
            </property>
          </activation>
          <properties>
            <javacpp.platform>android-arm</javacpp.platform>
            <javacpp.platform.root>${user.home}/Android/android-ndk/</javacpp.platform.root>
            <javacpp.platform.compiler>toolchains/arm-linux-androideabi-4.9/prebuilt/${os.name}-${os.arch}/bin/arm-linux-androideabi-g++</javacpp.platform.compiler>
          </properties>
        </profile>
    

    因此,可以下载android-ndk-r14b-linux-x86_64.zip,并且配置NDK环境为/root/Android/android-ndk:


    ndk配置路径

    编译环境准备好后,即可在javacpp_presets根目录用以下指令开始编译:

    mvn install -Pandroid-arm-default --projects ffmpeg -X
    

    编译过程中某些依赖库找不到的原因可能是SSL或被墙了,需要手动下载对应的库,放置到cppbuild目录:


    Maven编译通过后会在ffmpeg目录下生成一个target文件夹:


    target目录结构

    其中:
    ffmpeg.jar是JavaCpp编译出的java api
    ffmpeg-android-arm.jar是打包了所有ffmepg so及其jni库的jar包,参考下图:


    ffmpeg-android-arm库
    ffmpeg-javadoc.jar是JavaCpp根据注解编译的java api doc
    ffmpeg-sources.jar是ffmpeg\src目录的编译,具体有什么作用有待查证

    编译成功后,必须要做点什么,否则没有任何意义:
    1.创建一个Android工程



    其中把编译出的ffmpeg.jar和target\classes\lib\armeabi目录下的所有so拷贝到工程的libs目录下(不能直接使用ffmpeg-android-arm.jar是因为Android对so的校验机制,目前没有尝试去解决这种问题,如果有办法解决可以留言告诉我)


    直接使用ffmpeg-android-arm.jar
    target/classes/lib/armeabi目录下的所有库文件

    2.创建测试类
    通过一个最简单的测试类,测试JavaCpp FFMPEG的可用性:

    package com.example.ffmepgtest;
    
    import org.bytedeco.javacpp.avcodec;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.util.Log;
    
    public class MainActivity extends Activity {
        public static final String TAG = MainActivity.class.getSimpleName();
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            onTest();
        }
        
        public void onTest(){
            Log.d(TAG, " "+avcodec.avcodec_configuration().getString());
        }
    }
    
    程序运行最终结果

    可以看到,程序运行后可以调用libavcodec打印出FFmpeg的配置信息。说明通过JAVACPP技术在应用层调用FFMPEG(非指令途径调用FFMPEG)省去了JNI代码的编写,这对应用开发者来说是个多么好的消息。

    3.结束语

    使用JavaCpp FFMPEG这种框架方式,就好像打开了某道门,让应用开发省去了JNI开发成本,比如Tensorflow,Videoinput等开源库,在应用需要使用这些框架时,使用javacpp就能极大的减少应用开发周期。
    本文中讲述的JavaCpp例如 OpenCV、FFMpeg 等热门的开源项目是以开源贡献者已经完成JavaCpp代码转换文件的定义为前提的,关于自己的项目代码如何使用JavaCpp实现转换待我分析后再写一篇文章,感谢关注!

    相关文章

      网友评论

        本文标题:JavaCpp之FFMPEG实战教程

        本文链接:https://www.haomeiwen.com/subject/hkrdixtx.html