作者:谭东

时间:2017年9月19日

环境:Windows 8.1专业版

NDK版本:android-ndk-r14b

FFmpeg版本:FFmpeg 3.0.2 “Einstein”

我这里使用的Android Studio为2.3.3版本。

大名鼎鼎的FFmpeg可以说全球出名,基本上视频处理都是它,但是使用FFmpeg的技术门槛和难度也相对要求高一些。

那么我就先给大家简单引用别人的描述简单介绍下FFmpeg吧:

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多code都是从头开发的。多媒体视频处理工具FFmpeg有非常强大的功能包括视频采集功能、视频格式转换、视频抓图、给视频加水印等。

FFmpeg被许多开源项目采用,比如ffmpeg2theora,VLC, MPlayer, HandBrake, Blender, Google Chrome等。还有DirectShow/VFW的ffdshow(external project)和QuickTime的Perian (external project)也采用了FFmpeg。
由于FFmpeg是在LGPL/GPL协议下发布的(如果使用了其中一些使用GPL协议发布的模块则必须使用GPL协议),任何人都可以自由使用,但必须严格遵守LGPL/GPL协议。有很多播放软件都使用了FFmpeg的代码,但它们并没有遵守LGPL/GPL协议,没有公开任何源代码。我们应该对这种侵权行为表示耻辱。
2009年加入FFmpeg耻辱黑名单的播放软件:暴风影音、QQ影音、KMP、GOM Player、PotPlayer(2010)都在其列。
2009年2月,韩国名软KMPlayer被FFmpeg开源项目发现使用了它们的代码和二进制文件,但是没有按照规定/惯例开放相应说明/源码。因此被人举报,进入了FFmpeg官网上的耻辱黑名单。

2009年11月,网友roo_zhou向FFmpeg举报,指出QQ影音的credit只给出了修改的FFmpeg源码下载,声称是LGPL许可证。但实际是修改过的ffdshow,采用的是GPL许可证,之后QQ影音被正式加入到FFmpeg耻辱名单之列。
Libav项目启动之后,FFmpeg官方版本也仍然在一直维护中。FFmpeg与libav属于独立的两个项目。

-------------------------------------------------------------------------------------------------------------------------

就先介绍到这里。

FFmpeg大致有两种使用方式,第一种是命令行,这个最简单也最直接。不过这个比较适合Linux下,移动平台和Windows下还是需要单独编译源码,自己写C方法调用FFmpeg的API,然后编译成库,例如Android平台要编译成so库。这样难度和门槛就加大了,你要读懂和了解FFmpeg的C方法,C源码和API文档。其实很多用法可以看下官方英文文档,官方也有很多参考资料。我这里以Android平台为例,但是大同小异,毕竟方法都是C++的方法,IOS、Linux、Windows都通用的。

好了。接下来给大家讲解下编译和调用FFmpeg的C的API。

首先肯定是先要去FFmpeg官网下载最新的源码,然后在Linux下进行编译了。Android平台需要编译so库。

官网源码下载地址:http://ffmpeg.org/download.html

我之前写过一篇文章,讲解如何编译FFmpeg的。

《Ubuntu下编译Android版本的ffmepg so库及源码》
以及
《Ubuntu编译调用FFmpeg so库Api方法例子》
具体如何编译我就不说了,编译好后,进行下面的步骤。

1、Android Studio新建支持C++的项目。勾选Include C++ support。

2、新建好的项目大致结构这样。主要关注下图里红色的几个部分。

3.、接下来在项目的src下的main目录新建jniLibs目录,再新建对应的架构平台的文件夹名,然后把so库放进去。我这里只编译了armeabi平台的so库,所以结构是下图这样的。

4、把FFmpeg编译后的源码.h头文件拷贝到项目的libs目录里。

5、可以大致看下里面的,h里的方法和定义。

6、接下来就是编写配置我们的CMakeLists.txt了。下面是我写好的配置,大家可以参考。

# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.cmake_minimum_required(VERSION 3.4.1)find_library( # Sets the name of the path variable.log-lib# Specifies the name of the NDK library that# you want CMake to locate.log )set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../libs)add_library( avutil-55SHAREDIMPORTED )
set_target_properties( avutil-55PROPERTIES IMPORTED_LOCATION../../../../src/main/jniLibs/armeabi/libavutil-55.so )add_library( swresample-2SHAREDIMPORTED )
set_target_properties( swresample-2PROPERTIES IMPORTED_LOCATION../../../../src/main/jniLibs/armeabi/libswresample-2.so )
add_library( avcodec-57SHAREDIMPORTED )
set_target_properties( avcodec-57PROPERTIES IMPORTED_LOCATION../../../../src/main/jniLibs/armeabi/libavcodec-57.so )
add_library( avfilter-6SHAREDIMPORTED)
set_target_properties( avfilter-6PROPERTIES IMPORTED_LOCATION../../../../src/main/jniLibs/armeabi/libavfilter-6.so )
add_library( swscale-4SHAREDIMPORTED)
set_target_properties( swscale-4PROPERTIES IMPORTED_LOCATION../../../../src/main/jniLibs/armeabi/libswscale-4.so )
add_library( avdevice-57SHAREDIMPORTED)
set_target_properties( avdevice-57PROPERTIES IMPORTED_LOCATION../../../../src/main/jniLibs/armeabi/libavdevice-57.so )
add_library( avformat-57SHAREDIMPORTED)
set_target_properties( avformat-57PROPERTIES IMPORTED_LOCATION../../../../src/main/jniLibs/armeabi/libavformat-57.so )set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")add_library( native-libSHAREDsrc/main/cpp/native-lib.cpp )include_directories(libs/include)#target_include_directories(native-lib PRIVATE libs/include)target_link_libraries( native-lib swresample-2 avcodec-57 avfilter-6 swscale-4 avdevice-57 avformat-57${log-lib} )

7、接下来我们看下默认生成的cpp文件夹里的native-lib.cpp的里面的C方法例子规范。

#include <jni.h>
#include <string>extern "C" JNIEXPORT jstring JNICALL
Java_com_tandong_testffmpeg_MainActivity_stringFromJNI(JNIEnv *env,jobject /* this */) {std::string hello = "Hello from C++";return env->NewStringUTF(hello.c_str());
}

很简单对不对。我们可以按照这个规范写我们的其他测试和调用FFmpeg的API的C++方法了。

#include <jni.h>
#include <string>extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>JNIEXPORT jstring JNICALL
Java_com_tandong_testffmpeg_MainActivity_stringFromJNI(JNIEnv *env,jobject /* this */) {std::string hello = "Hello from C++";return env->NewStringUTF(hello.c_str());
}JNIEXPORT jstring JNICALL
Java_com_tandong_testffmpeg_MainActivity_stringFromJNI2(JNIEnv *env,jobject /* this */) {return env->NewStringUTF("测试");
}/*** 获取FFmpeg支持的协议格式*/
JNIEXPORT jstring JNICALL
Java_com_tandong_testffmpeg_MainActivity_getUrlProtocolInfo(JNIEnv *env, jobject) {char info[40000] = {0};av_register_all();struct URLProtocol *pup = NULL;struct URLProtocol **p_temp = &pup;avio_enum_protocols((void **) p_temp, 0);while ((*p_temp) != NULL) {sprintf(info, "%sInput: %s\n", info, avio_enum_protocols((void **) p_temp, 0));}pup = NULL;avio_enum_protocols((void **) p_temp, 1);while ((*p_temp) != NULL) {sprintf(info, "%sInput: %s\n", info, avio_enum_protocols((void **) p_temp, 1));}return env->NewStringUTF(info);
}/*** 获取avcodec的库的版本号*/
JNIEXPORT jstring JNICALL
Java_com_tandong_testffmpeg_MainActivity_getAvCodecVersion(JNIEnv *env, jobject) {char version[50];avcodec_register_all();sprintf(version, "%d", avcodec_version());return env->NewStringUTF(version);
}/*** 获取avformat的库的协议*/
JNIEXPORT jstring JNICALL
Java_com_tandong_testffmpeg_MainActivity_getAvFormatLicense(JNIEnv *env, jobject) {std::string license = avformat_license();return env->NewStringUTF(license.c_str());
}}

这些是我写的几个调用API的方法,这些都是很简单的,后面有很多复杂的功能,写法就会更加的复杂,难度也会更大。

我们可以根据它的.h头文件或者官方源码文档,查看这个方法传入的参数含义和类型以及返回的类型及作用。

下面是官方文档查看及源码。

8、紧接着,我们编写我们的JAVA来调用JNI的方法。

package com.tandong.testffmpeg;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// Example of a call to a native methodTextView tv = (TextView) findViewById(R.id.sample_text);tv.setText(getUrlProtocolInfo());}/*** A native method that is implemented by the 'native-lib' native library,* which is packaged with this application.*/public native String stringFromJNI();public native String stringFromJNI2();public native String getUrlProtocolInfo();public native String getAvCodecVersion();public native String getAvFormatLicense();// Used to load the 'native-lib' library on application startup.static {System.loadLibrary("native-lib");}
}

这个就很简单了,就不给大家解释了。

9、最后就是编译打包运行了,编译运行后,就会生成我们的so库。

调用编译就先给大家讲解到这里,请继续关注

版权所有,尊重版权。
微信公众号:

Android编译调用FFmpeg API,自己写方法,编译so库相关推荐

  1. axios vue 回调函数_VUE使用axios调用后台API接口的方法

    VUE使用axios调用后台API接口的方法 引言 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式JavaScript框架.与其它大型框架不同的是,Vue 被设计为可 ...

  2. FFmpeg Android 学习(一):Android 如何调用 FFMPEG 编辑音视频

    一.概述 在Android开发中,我们对一些音视频的处理比较无力,特别是编辑音视频这部分.而且在Android上对视频编辑方面,几乎没有任何API做支持,MediaCodec(硬编码)也没有做支持.那 ...

  3. Android Java调用ffmpeg命令

    0. 前言 ffmpeg命令很强大,但是在Android工程中无法执行可执行文件ffmpeg,即无法使用ffmpeg.  本文介绍把ffmpeg改造成库文件,然后通过JNI调用它,即可实现在Java中 ...

  4. Android之调用第三方API导航(高德,百度,google)

    一:效果图(点击路线调用API) 二:实现步骤: 1.判断是否安装各个地图软件 /*** 判断是否安装目标应用** @param packageName 目标应用安装后的包名* @return 是否已 ...

  5. android ffmpeg编译动态库,最简单的android studio调用ffmpeg动态库

    准备工作: 1.编译好的ffmpeg动态库.so文件,以及ffmpeg的头文件: 2.android studio开发环境,包括NDK等可用环境: 步骤一: 新建一个android studio工程, ...

  6. Android P 调用隐藏API限制原理

    随着Android P预览版的发布,谷歌在改进系统稳定性的措施上又增加了新的限制,即应用程序引用非SDK接口,无论采用直接.反射.JNI获取等手段都将受到限制.在谷歌提供的预览版文档&& ...

  7. Android Studio调用百度API(图片文字识别)

    1.登录百度AI平台(https://ai.baidu.com/),下载license文件 包名填写内容: 下载好的文件夹内包含四个文件 (OCR-Android-SDK.md文件里有使用说明) (1 ...

  8. Android Fragment 调用宿主Activity 里面的方法

    方法 1 : 直接在Fragment 写 MainActivity main = (MainActivity) getActivity();main.xx; // xx 是 MainActivity ...

  9. android aidl调用进程间服务的方法

    我就拿最近做的项目来说明了,首先创建一个IFMService.aidl的接口文件,在R.java的目录下会自动生成IFMService.java 的文件, 接口文件的内容如下: package net ...

最新文章

  1. oracle 字符集 AL32UTF8、UTF8
  2. YII2 载入默认值 loadDefaultValues
  3. react native windows 搭建(完整版)
  4. 使用WordPress的Kyma plugin同Kyma断开连接的实现
  5. Python网路请求(GET示例)
  6. asp.net在动态网页中的使用技巧
  7. delphi中webbrowser的用法
  8. 如何对全站进行死链接检测?
  9. VC6 VS2010 环境变量
  10. 企业级Docker Registry —— Harbor搭建和使用
  11. PHP require、include、require_once、include_once用法及区别
  12. freemarker 遍历 map
  13. Ubuntu下bazel卸载与安装
  14. 无剑100SOC(wujian100)挂UART外设之④修改SDK
  15. 4.2 Python 实例5-身体质量指数BMI
  16. Java实现将字符串进行Base64跟GZip结合解密 Java实现Base64 + GZIP解密处理并且输出明文字符
  17. MySQL性能优化(四):SQL优化
  18. 大容量邮箱如何注册?TOM VIP邮箱帮你轻松搞定
  19. 第七周——复数模板类
  20. MindNode 5.0.1 pro for mac 破解版

热门文章

  1. vue3 diff算法优化
  2. HiCopyTrader跟单系统启动失败,错误提示:api ms win crt xxxx.dll 之类文件缺失,怎么办
  3. “远程网络教学系统”
  4. 不动产登记:摈除“黑暗的大数据”
  5. kali的root账户的密码是多少?
  6. parseFloat() 函数
  7. 2022制冷与空调设备运行操作特种作业证考试题库模拟考试平台操作
  8. 浅谈千万级PV/IP规模高性能高并发网站架构(转自老男孩)
  9. 高并发:线程、线程锁与线程池(精华),文中附上一个手写代码实现线程池视频(c/c++语言)
  10. 5G时代必学的WebRTC音视频通话技术