Media技术杂烩Android知识共享Android开发经验谈

JavaCpp之FFMPEG实战教程

2017-12-13  本文已影响182人  Young_Allen

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实现转换待我分析后再写一篇文章,感谢关注!

上一篇 下一篇

猜你喜欢

热点阅读