FFmpeg:初步编译使用[Android]
1.安装NDK:http://dl.google.com/android/ndk/android-ndk-r9-linux-x86.tar.bz2
sudo gedit ~/.bashrc
末尾添加:
#add NDK
PATH=$PATH:/home/sheldon/Android/android-ndk-r9/
source ~/.bashrc : 立即生效配置,可以使用"ndk-build"指令
2.FFmpeg官方网站 http://www.ffmpeg.org/ 下载源代码.
3.修改configure,将生成lib的版本号置于.so之前,以防Android无法加载:
#SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
#LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
#SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
#SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
VERSION_SCRIPT_POSTPROCESS_CMD="cat"
4.编写build_android.sh脚本文件,如果从网上直接copy过去可能会是dos格式,使用dos2unix build_android.sh 转换一下,删掉多余空格:
#!/bin/bash : 以下三个变量根据自己系统环境配置
NDK=/home/sheldon/Android/android-ndk-r9/
SYSROOT=$NDK/platforms/android-9/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86
function build_one
{
./configure \
--prefix=$PREFIX \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-doc \
--disable-symver \
--enable-small \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=linux \
--arch=arm \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one
5.增加执行权限,执行:
$chmod a+x build_android.sh
$./build_android.sh
生成:[头文件]android/arm/include/*.h 和 [动态库文件]android/arm/lib/*.so
6.创建Android工程使用lib:
(1)创建一个新的Android工程FFmpeg4android。
(2)在工程目录下创建jni文件夹,与java目录同级。
(3)在jni下创建prebuilt/armeabi目录,然后:
将上面FFmpeg source code编译生成的so文件(带版号的真实库而不是链接文件)放入到该目录下的armeabi目录;
将android/arm/include/下的所有头文件夹拷贝到该jni目录下.
(4)创建包含native方法的类(java层直接调用的接口),先在src/main/java/下创建FFmpegNative.java类文件。主要包括加载so库文件和一个native测试方法两部分,其内容如下:
package com.li.sheldon.ffmpeg4android; /**
* Created by sheldon on 17-1-4.
*/
public class FFmpegNative {
static{
System.loadLibrary("avcodec-57");
System.loadLibrary("avdevice-57");
System.loadLibrary("avfilter-6");
System.loadLibrary("avformat-57");
System.loadLibrary("avutil-55");
System.loadLibrary("swresample-2");
System.loadLibrary("swscale-4");
System.loadLibrary("ffmpegjni");
}
private native int ffmpeg_h264(int codecID); public int test_h246(int id){
return ffmpeg_h264(id);
}
}
(5)用javah创建.头文件:
-classpath <路径> 用于装入类的路径
-d <目录> 输出目录
-jni 生成 JNI样式的头文件(默认)
javah -classpath /FFmpeg4android/app/src/main/java/ -d ./ -jni com.li.sheldon.ffmpeg4android.FFmpegNative
-classpath 后面的路径是指包”com.li.sheldon.ffmpeg4android”所在的根路径
会在当前目录产生com_li_sheldon_ffmpeg4android_FFmpegNative.h的C头文件;
(6)根据头文件名,建立相同名字才C源文件com_li_sheldon_ffmpeg4android_FFmpegNative.c
在这个源文件中实现头文件中定义的方法,核心部分代码如下:
#include "com_li_sheldon_ffmpeg4android_FFmpegNative.h"
JNIEXPORT jint JNICALL Java_com_li_sheldon_ffmpeg4android_FFmpegNative_ffmpeg_1h264
(JNIEnv* env, jobject thiz, jint codecID)
{
AVCodec* codec = NULL;
av_register_all();//该函数在所有基于ffmpeg的应用程序中几乎都是第一个被调用的。只有调用了该函数,才能使用复用器,编码器等
codec = avcodec_find_decoder(codecID);//通过code ID查找一个已经注册的音视频编码器。H264的codecID是28,所以我们java那边传28下来如果检测到H264注册过了这边codec就不为空,返回0
if(codec != NULL){
return 0;
}else{
return -1;
}
}
(7)编写Android.mk,内容如下:
#APP_ABI := armeabi armeabi-v7a x86
ifeq ($(APP_ABI), x86)
LIB_NAME_PLUS := x86
else
LIB_NAME_PLUS := armeabi
endif
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= avcodec-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES:= prebuilt/$(LIB_NAME_PLUS)/libavcodec-57.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= avdevice-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES:= prebuilt/$(LIB_NAME_PLUS)/libavdevice-57.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= avfilter-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES:= prebuilt/$(LIB_NAME_PLUS)/libavfilter-6.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= avformat-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES:= prebuilt/$(LIB_NAME_PLUS)/libavformat-57.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avutil-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES := prebuilt/$(LIB_NAME_PLUS)/libavutil-55.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := swresample-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES := prebuilt/$(LIB_NAME_PLUS)/libswresample-2.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := swscale-prebuilt-$(LIB_NAME_PLUS)
LOCAL_SRC_FILES := prebuilt/$(LIB_NAME_PLUS)/libswscale-4.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
ifeq ($(APP_ABI), x86)
TARGET_ARCH:=x86
TARGET_ARCH_ABI:=x86
else
LOCAL_ARM_MODE := arm
endif
LOCAL_MODULE := libffmpegjni
LOCAL_SRC_FILES := com_li_sheldon_ffmpeg4android_FFmpegNative.c
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -lz
LOCAL_SHARED_LIBRARIES:= avcodec-prebuilt-$(LIB_NAME_PLUS) \
avdevice-prebuilt-$(LIB_NAME_PLUS) \
avfilter-prebuilt-$(LIB_NAME_PLUS) \
avformat-prebuilt-$(LIB_NAME_PLUS) \
avutil-prebuilt-$(LIB_NAME_PLUS) \
swresample-prebuilt-$(LIB_NAME_PLUS) \
swscale-prebuilt-$(LIB_NAME_PLUS)
LOCAL_C_INCLUDES += -L$(SYSROOT)/usr/include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
ifeq ($(APP_ABI), x86)
LOCAL_CFLAGS := -DUSE_X86_CONFIG
else
LOCAL_CFLAGS := -DUSE_ARM_CONFIG
endif
include $(BUILD_SHARED_LIBRARY)
(8) 编写Application.mk, 指定编译平台[可省略]
APP_PROJECT_PATH := $(call my-dir)/..
APP_MODULES := libffmpegjni
-------------------
编译so文件:
打开cmd命令行,进入FFmpeg4Android\jni目录下,执行如下命令:
ndk-build
截止本步骤完成,将在FFmpeg4android/app/src/main/libs/armeabi/下另外生成了libffmpegjni.so文件, cp到FFmpeg4android/app/libs/armeabi/下由java类加载。
ps:共享库将被拷贝到 $PROJECT/obj/local 和 $PROJECT/libs/<abi> (stripped) 主要是用在将已经编译好的第三方库.
-------------------------如果ndk编译报错,加下面一段
build.greadle(app):
sourceSets.main{
jniLibs.srcDir 'libs'
jni.srcDirs = [] //disable automatic ndk-build call
}
(9)修改layout/main.xml,给TextView增加id,以便在代码中操作它:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.li.sheldon.ffmpeg4android.MainActivity"> <TextView
android:id="@+id/hello_ffmpeg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</RelativeLayout>
(10)增加一个Activity实现类FFmpeg4AndroidActivity,在OnCreate方法中调用native函数将值传给TextView控件,打包运行即可。FFmpeg4AndroidActivity代码如下:
package com.li.sheldon.ffmpeg4android; import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int codec_id=28;
FFmpegNative ffmpeg = new FFmpegNative();
int tmp = ffmpeg.test_h246(codec_id); //28 is the H264 Codec ID
TextView tv = (TextView)this.findViewById(R.id.hello_ffmpeg);
tv.setText(tmp==0?"Support Codec ID:"+codec_id:"Not support Codec ID:"+codec_id);
}
}
代码中的28是H264的编解码枚举类型定义的ID,如果能找到H264编解码,表明可以成功使用FFmpeg库文件。
android 代码和动态库已传至github : https://github.com/dragonforgithub/FFmpeg4Android.git
记录FFmpeg 雷神博客:http://blog.csdn.net/leixiaohua1020/article/details/44226355 (致敬永远的雷神)
FFmpeg:初步编译使用[Android]的更多相关文章
- ffmpeg(2.6) rockplayer android 下编译 小记.
最近因为一些需求,开始学习 ffmgeg 在android 上使用. 使用的环境: 1,VMware V8 虚似机 安装的 FedoraV18 系统.(下载地址,请baidu),虚似机,最好有20-3 ...
- FFmpeg 1.2 for Android 生成一个动态库
上一篇<FFmpeg 1.2 for Android 编译动态库>里沃特跟大家介绍了如何编译动态库,但当时所生成的动态库总共包含10个so文件,这样要是加载起来会严重影响软件的启动速度,后 ...
- Mac系统下编译支持Android平台的最新X264编码器
Mac系统下编译支持Android平台的最新X264编码器 原文来自 http://www.mingjianhua.com,转载请注明出处 1.首先去官网下载最新的x264源代码,解压到任意目录 ht ...
- Atitit.反编译apk android源码以及防止反编译apk
Atitit.反编译apk android源码以及防止反编译apk 1.1. Tool apk逆向助手1 1.2. 二.使用dex2jar + jd-gui 得到apk的java源码1 1.3. 用 ...
- 项目androidAnt编译打包Android项目
时间紧张,先记一笔,后续优化与完善. Ant编译打包Android项目 在Eclipse中对Android项目停止编译和打包如果项目比较大的话会比较慢,所以改为Ant工具来停止编译和打包 Ant环境配 ...
- 如何把iOS代码编译为Android应用
新闻 <iPhone 6/6 Plus中国销量曝光:单月销量650万>:据iSuppli Corp.中国研究总监王阳爆料,iPhone 6和iPhone 6 Plus在国内受欢迎的情况大大 ...
- 一、cocos2d-x 3.0 final使用httpclient编译到android,须要用到的android.mk
今天写一个网络框架,在vs上面非常欢快的执行车,心想,尼玛!cocos2d-x 3.0这么方便,预计不久的将来我就能回家种地了,由于不用程序猿了,直接cocos2dstudio拖界面了= =!!. 写 ...
- 通过ant脚本编译打包android工程
通过ant脚本,编译打包android工程 1.Android程序编译.打包.签名.发布的三种方式: 方式一:命令行手动编译打包 方式二:使用ant自动编译打包 方式三:使用eclipse+AD ...
- Android - Ant自动编译打包android项目 -- 1(转)
1. 背景: Eclipse用起来虽然方便,但是编译打包android项目还是比较慢,尤其当要将应用打包发布到各个渠道时,用Eclipse手动打包各种渠道包就有点不切实际了,这时候我们用到Ant帮我 ...
随机推荐
- linux下添加环境变量
我安装完 RedHat Linux 5 之后,在终端使用一些命令,如: ifcinfig 查看本机的IP,发现不能使用此命令,提示说“command not found”,这该怎么办呢 想想肯定是环境 ...
- Python递归报错:RuntimeError: maximum recursion depth exceeded in comparison
Python中默认的最大递归深度是989,当尝试递归第990时便出现递归深度超限的错误: RuntimeError: maximum recursion depth exceeded in compa ...
- 在后台启动受管服务器经常报错:Server may already be running
报错如下: 1. Unable to obtain lock on /usr/local/odrive/odrive_chen/Middleware/user_projects/domains/oim ...
- Python之路 day3 函数定义 *args及**kwargs
#!/usr/bin/env python # -*- coding:utf-8 -*- #Author:ersa import time # def logger(): # time_format ...
- VNC SERVER配置
vnc的配置网上有很多 普通用户的配置没有怎么写 根据下面这个说法 https://www.digitalocean.com/community/tutorials/how-to-install-an ...
- link和@import导入css文件的区别
(二者的区别其实是基础问题,但由于本人经常会忽略掉使用@import导入css文件这种方式,所以记录下来增加印象^^) 首先二者的引入方式: link:<link rel="style ...
- 使用CXF发布WebService
这里普及一下WebService和cxf的知识.关于webservice和cxf: WebService.各种提供服务的组件 .企业总线.通讯总线(ESB)CXF:是一个SOA框架,Axi ...
- JS学习笔记--仿手机发送内容交互
学习JS笔记----记录上课中学习的知识点,分享下老师教的内容: 1.html内容 <div id="box"> <div id="message&qu ...
- Galera集群server.cnf参数调整--前言
文档安排: 前言部分会简述下galera集群,正文中会针对我们线上的环境,在不断业务的情况下,进行参数调整的话,有些参数不能够进行配置,会以#***的形式写入配置文件中,文档也会进行进一步说明. 如果 ...
- Linux文件的建立、复制、删除和移动命令
mkdir命令一.mkdir 命令使用权限 所有用户都可以在终端使用 mkdir 命令在拥有权限的文件夹创建文件夹或目录. 二.mkdir 命令使用格式 格式: mkdir [选项] DirName ...