Mac OS下为Android Studio编译FFmpeg解码库的详细教程

NDK部分
1、下载ndk
这里就一笔带过了。

2、解压ndk
不要解压,文件权限会出错。执行之,会自动解压,然后mv到想放的地方。我放到了”/usr/local/bin/android-ndk-r10d”(此目录之后用$NDK_DIR指代)。

3、下载Ffmpeg
我下的是2.5.3版本。

4、解压Ffmpeg
解压Ffmpeg到$NDK_DIR/sources/ffmpeg-2.5.3。

5、修改Ffmpeg编译配置
在ffmpeg-2.5.3目录下把configure文件中的这几行,目的是去掉默认生成的库名字libavcodec.so.55最后那个”55″的版本号。

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)'


6、编译Ffmpeg
在ffmpeg-2.5.3目录下创建文件build_android.sh。
注意前三行要按照自己的路径正确配置。

#!/bin/bash
NDK=/usr/local/android-ndk-r10d
SYSROOT=$NDK/platforms/android-15/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
function build_one
{
./configure \
 --prefix=$PREFIX \
 --enable-shared \
 --disable-static \
 --disable-doc \
 --disable-ffmpeg \
 --disable-ffplay \
 --disable-ffprobe \
 --disable-ffserver \
 --disable-avdevice \
 --disable-doc \
 --disable-symver \
 --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

保存后执行

sudo chmod +x build_android.sh
./build_android.sh

编译会花上一段时间。

7、查看编译结果

编译完成后$NDK_DIR/sources/ffmpeg-2.5.3下面会多出一个android目录,里面就是我们想要的编译好的库。

[cg@local]# ls -R android/
arm

android//arm:
Android.mk include lib

android//arm/include:
libavcodec libavfilter libavformat libavutil  libswresample libswscale

android//arm/include/libavcodec:
avcodec.h  avfft.h   dv_profile.h dxva2.h   old_codec_ids.h vaapi.h   vda.h   vdpau.h   version.h  vorbis_parser.h xvmc.h

android//arm/include/libavfilter:
asrc_abuffer.h avcodec.h  avfilter.h  avfiltergraph.h buffersink.h buffersrc.h  version.h

android//arm/include/libavformat:
avformat.h avio.h  version.h

android//arm/include/libavutil:
adler32.h  avstring.h  cast5.h   downmix_info.h hash.h   macros.h   opt.h   replaygain.h  time.h
aes.h   avutil.h   channel_layout.h error.h   hmac.h   mathematics.h parseutils.h  ripemd.h   timecode.h
attributes.h  base64.h   common.h   eval.h   imgutils.h  md5.h   pixdesc.h  samplefmt.h  timestamp.h
audio_fifo.h  blowfish.h  cpu.h   ffversion.h  intfloat.h  mem.h   pixelutils.h  sha.h   version.h
audioconvert.h bprint.h   crc.h   fifo.h   intreadwrite.h motion_vector.h pixfmt.h   sha512.h   xtea.h
avassert.h  bswap.h   dict.h   file.h   lfg.h   murmur3.h  random_seed.h stereo3d.h
avconfig.h  buffer.h   display.h  frame.h   log.h   old_pix_fmts.h rational.h  threadmessage.h

android//arm/include/libswresample:
swresample.h version.h

android//arm/include/libswscale:
swscale.h version.h

android//arm/lib:
libavcodec-56.so libavfilter-5.so libavformat-56.so libavutil-54.so libswresample-1.so libswscale-3.so pkgconfig
libavcodec.so  libavfilter.so  libavformat.so  libavutil.so  libswresample.so libswscale.so

android//arm/lib/pkgconfig:
libavcodec.pc libavfilter.pc libavformat.pc libavutil.pc  libswresample.pc libswscale.pc

其中libavcodec.so、libavfilter.so、libavformat.so、libavutil.so、libswresample.so、libswscale.so都是软链,没有用,可以删掉。

8、给Ffmpeg库写Android.mk使其可用
创建$NDK_DIR/sources/ffmpeg-2.5.3/android/arm/Android.mk文件,内容如下:
要注意其中.so前面的数字应该改成你的ffmpeg版本编译出来的数字。

LOCAL_PATH:= $(call my-dir)

 include $(CLEAR_VARS)
LOCAL_MODULE:= libavcodec
LOCAL_SRC_FILES:= lib/libavcodec-56.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)

 include $(CLEAR_VARS)
LOCAL_MODULE:= libavformat
LOCAL_SRC_FILES:= lib/libavformat-56.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)

 include $(CLEAR_VARS)
LOCAL_MODULE:= libswscale
LOCAL_SRC_FILES:= lib/libswscale-3.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)

 include $(CLEAR_VARS)
LOCAL_MODULE:= libavutil
LOCAL_SRC_FILES:= lib/libavutil-54.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)

 include $(CLEAR_VARS)
LOCAL_MODULE:= libavfilter
LOCAL_SRC_FILES:= lib/libavfilter-5.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)

 include $(CLEAR_VARS)
LOCAL_MODULE:= libswresample
LOCAL_SRC_FILES:= lib/libswresample-1.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)

至此ndk配置完毕,后面是配置Android Studio的部分。

Android Studio部分
Android Studio和Eclipse不太一样,它有一定的自动生成Android.mk并自动搞定JNI的能力。
但目前还并不足以让我们使用起来Ffmpeg库。
因此我们的思路是禁用掉Android Studio自动ndk-build的功能,手动编译我们的C代码达到目的。

首先当然要新建一个Android Studio项目。
我们使用$ROOT_DIR指代项目根目录。

1、Android Studio配置ndk路径
$ROOT_DIR/local.properties原先只配置了sdk。

sdk.dir=/usr/local/bin/android-sdk-macosx

给它增加一行ndk的配置

sdk.dir=/usr/local/bin/android-sdk-macosx
ndk.dir=/usr/local/bin/android-ndk-r10d

2、配置build.gradle
项目里面有两个build.gradle,一个在根目录下,一个在$ROOT_DIR/app/src下,我们要修改的是后者。
A>添加这一段以禁用自动ndk-build。

sourceSets.main.jni.srcDirs = []

B>添加这一段让它知道用库

  ndk {
   abiFilter "armeabi"
   moduleName "ovsplayer"
   ldLibs "log", "z", "m", "jnigraphics", "android"
  }

修改后的build.gradle是这样的。

android {
 compileSdkVersion 21
 buildToolsVersion "21.1.1"

 sourceSets.main.jni.srcDirs = [] // 禁用自动执行ndk-build
 defaultConfig {
  applicationId "com.example.chengang.myapplication"
  minSdkVersion 15
  targetSdkVersion 21
  versionCode 1
  versionName "1.0"
  ndk {
   abiFilter "armeabi"
   moduleName "ovsplayer" // 这个是C文件的名字
   ldLibs "log", "z", "m", "jnigraphics", "android"
  }
 }
 buildTypes {
  release {
   minifyEnabled false
   proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  }
 }
}

3、生成头文件
执行命令,注意路径要根据自己的情况更改。

代码如下:

javah -d jni -classpath ..\..\build\intermediates\classes\debug com.example.nativeapp.app.MainActivity

会生成这个文件$ROOT_DIR/app/src/main/jni/com_example_chengang_myapplication_MainActivity.h

4、编写C文件
$ROOT_DIR/app/src/main/jni/ovsplayer.c内容如下:

#include <stdio.h>
#include <stdlib.h>

#include "com_example_chengang_myapplication_MainActivity.h"
#include "libavutil/avutil.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"

JNIEXPORT jstring JNICALL Java_com_example_chengang_myapplication_MainActivity_getStringFromNative
 (JNIEnv * env , jobject obj)
 {
  const char *url = "/mnt/sdcard/1.mp4";
  av_register_all();

  AVFormatContext *pFormatCtx = NULL;
  int ret = avformat_open_input(&pFormatCtx, url, NULL, NULL);

  ret = avformat_find_stream_info(input_context, NULL);
  int streamNum = input_context->nb_streams;

  char wd[512];
  sprintf(wd, "AVCODEC VERSION %u\n, streamNum[%d]"
    , avcodec_version()
    , streamNum
    );
  return (*env)->NewStringUTF(env, wd);
 }

5、编写Java文件
$ROOT_DIR/app/src/main/java/com/example/chengang/myapplication/MainActivity.java内容如下。
其中getStringFromNative()方法是我们实现的,打印了Ffmpeg库的版本号(我编译的这个是3673444)和视频文件的信息出来。

package com.example.chengang.myapplication;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  TextView view = (TextView) findViewById(R.id.mytext);
  view.setText(this.getStringFromNative());
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.menu_main, menu);
  return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  // Handle action bar item clicks here. The action bar will
  // automatically handle clicks on the Home/Up button, so long
  // as you specify a parent activity in AndroidManifest.xml.
  int id = item.getItemId();

  //noinspection SimplifiableIfStatement
  if (id == R.id.action_settings) {
   return true;
  }

  return super.onOptionsItemSelected(item);
 }

 public native String getStringFromNative();
 static {
  System.loadLibrary("swresample-1");
  System.loadLibrary("avutil-54");
  System.loadLibrary("avformat-56");
  System.loadLibrary("avcodec-56");
  System.loadLibrary("swscale-3");
  System.loadLibrary("ovsplayer");
 }
}

附上布局文件是这样的。

<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:paddingLeft="@dimen/activity_horizontal_margin"
 android:paddingRight="@dimen/activity_horizontal_margin"
 android:paddingTop="@dimen/activity_vertical_margin"
 android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

 <TextView
  android:id="@+id/mytext"
  android:text="@string/hello_world" android:layout_width="wrap_content"
  android:layout_height="wrap_content" />

</RelativeLayout>

6、编写项目Android.mk
Android.mk放到$ROOT_DIR/app/build/intermediates/ndk/debug/下。
注意其中的绝对路径”/Users/chengang/Code/Android/MyApplication4″是咱们的$ROOT_DIR。

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := ovsplayer
LOCAL_LDLIBS := \
 -lm \
 -ljnigraphics \
 -landroid \
 -llog \
 -lz \

LOCAL_SHARED_LIBRARIES := libavformat libavcodec libswscale libavutil

LOCAL_SRC_FILES := \
 /Users/chengang/Code/Android/MyApplication4/app/src/main/jni/ovsplayer.c \

LOCAL_C_INCLUDES += /Users/chengang/Code/Android/MyApplication4/app/src/main/jni
LOCAL_C_INCLUDES += /Users/chengang/Code/Android/MyApplication4/app/src/debug/jni

include $(BUILD_SHARED_LIBRARY)
$(call import-module,ffmpeg-2.5.3/android/arm)

简单说下LOCAL_LDLIBS和LOCAL_SHARED_LIBRARIES的区别,前者链接系统库,后者链接第三方库。
并不能换着用。

7、编译C代码
在终端下执行这个命令编译C代码。

代码如下:

/usr/local/bin/android-ndk-r10d/ndk-build NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/Users/chengang/Code/Android/MyApplication4/app/build/intermediates/ndk/debug/Android.mk APP_PLATFORM=android-21 NDK_OUT=/Users/chengang/Code/Android/MyApplication4/app/build/intermediates/ndk/debug/obj NDK_LIBS_OUT=/Users/chengang/Code/Android/MyApplication4/app/build/intermediates/ndk/debug/lib APP_ABI=armeabi

8、运行项目
回到Android Studio中Ctrl+R运行项目。
会看到手机上打印出Ffmpeg库的版本号(我编译的这个是3673444)和视频文件的信息出来。
Ffmpeg库已经可以调用了,然后继续写自己的逻辑就好了。

9、另外
另外说两个C代码中可能遇见的错误:
A>如果你通过标准库想得到文件大小,又写错了文件名。安卓上,在不存在的文件的句柄上执行fseek会报如下错误:”could not disable core file generation.”;
B>如果avformat_open_input()返回-1330794744了。那有两种可能,一是你忘记调用av_register_all()了,二是编译Ffmpeg的时候没有编译进对应的DEMUXER或者指定了disable-everything。

(0)

相关推荐

  • mac系统下载、安装、使用AndroidStudio

    1.下载AndroidStudio AndroidStudio官网下载地址: http://developer.android.com/intl/zh-cn/sdk/index.html AndroidStudio非官网下载地址: http://www.android-studio.org java8下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 注:以下安装软件计

  • Mac Android Studio快捷键整理

    为了提高工作效率,特地的整理了MAC 版 Android Studio 快捷键的整理,如果后续还有,在继续补充! ⌥-> option|alt ⇧->shift ⌃->control ⌘->command ⎋->esc ↑↓←→ Code  alt+F7:Find usage alt+command+L:格式化代码 alt+control+O:优化import(去掉无用的import) command+O:Override Methods command+I:Implemen

  • Mac 下 Android Studio 不打印日志的解决办法

    Mac 下 Android Studio 不打印日志的解决办法 前言: 在 Mac 下使用 Android Studio 时常会遇到 Android Monitor 突然不打印日志的情况,目前我知道的有三个方法: 1.重启 Android Studio 这个不需要多说,点击 Android Studio 的 File => Invalidate caches / Restart ,选择 Just Restart 2.重启 adb 命令行下输入:adb kill-server 关闭 adb,adb

  • Mac OS下为Android Studio编译FFmpeg解码库的详细教程

    NDK部分 1.下载ndk 这里就一笔带过了. 2.解压ndk 不要解压,文件权限会出错.执行之,会自动解压,然后mv到想放的地方.我放到了"/usr/local/bin/android-ndk-r10d"(此目录之后用$NDK_DIR指代). 3.下载Ffmpeg 我下的是2.5.3版本. 4.解压Ffmpeg 解压Ffmpeg到$NDK_DIR/sources/ffmpeg-2.5.3. 5.修改Ffmpeg编译配置 在ffmpeg-2.5.3目录下把configure文件中的这几

  • android studio编译jar包或者aar包的方法教程详解

    1. 在原有工程目录右键-> new ->Module->: 2. 选择library: 3. 一路next,最后finish: 4. 在新生成的lib module下的build.gradle中添加如下代码: task makeJar(type: Copy) { //删除存在的 delete 'build/outputs/aar/plugin-release.aar' delete 'libs/' //设置拷贝的文件来源 from('build/outputs/aar/') ////新

  • Android Studio引入FFmpeg的方法

    新建C++工程 新建 两个externalNativeBuild 一个sourceSets(指定so路径) android { compileSdkVersion 29 buildToolsVersion "29.0.3" defaultConfig { ... externalNativeBuild { cmake { cppFlags "-std=c++11 -frtti -fexceptions" abiFilters 'armeabi-v7a' } } so

  • Ubuntu16.04 LTS 下安装 Android Studio 2.2.2 的详细步骤

    下载 Android SDK,官网:www.android.com我相信很多人跟我一样,进不去.Android Studio 中文官网 www.android-studio.org 进去下载, 在终端解压到想安装SDK的目录(设SDK目录为 $ASDK_HOME )即安装完成. 进入目录 $ASDK_HOME/tools/,终端运行命令 ./android 进入 SDK Manager. 通过这个软件,可以选择下载相关的开发包,有不同版本的 SDK 及其源码文档等,注意:必须下载 Extras

  • 浅谈Android Studio JNI生成so库

    1.新建Android studio工程 2.新建class:AppKey.java.主要为了保存密钥 代码块 package com...adminapp.lib.utils.jni; /** * Created by seven on 16/9/8. */ public class AppKey { static { System.loadLibrary("AppKey"); } public static native String WechatId(); public stat

  • Android打包篇:Android Studio将代码打包成jar包教程

    一.新建一个as项目,再新建一个model模块 然后再app中的build.gradle中添加model的依赖.然后编译项目. 二.编译完成后,打开model下的build--intermediates--bundles目录,目录下有两个文件夹,debug,default,在default文件夹下有一个classess.jar,就是编译完成的jar包, 这里需要主要的是:因为我们使用的 as 版本不一致,所以会导致classess.jar包的目录页会不一样,不过最终的目录还是在build--in

  • Android Studio安装配置、环境搭建详细步骤及基本使用的详细教程

    前言 Android Studio的安装配置及使用篇终于来啦~ 废话不多说,以下针对JDK正确安装(及其环境变量配置完毕,即Java开发环境下).Android Studio的安装,配置,以及创建工程.主题字体更换.窗口工具.布局.快捷方式等的基本使用逐一说明. 安装java 下载Java安装包(jdk,网上有很多下载地址,最好去官网下:https://www.java.com/zh_CN/),安装完后记得配置环境变量: 在"系统变量"新建一个变量名为JAVA_HOME的变量,变量值为

  • 在Android Studio中Parcelable插件的简单使用教程

    在Android Studio中,你可以很快速的使用Parcelable插件进行实体类的序列化的实现,使用该插件后,你的实体类可以快速的实现Parcelable接口而不用写额外的代码.因为该插件会帮你快速的生成必须提供的方法,可以说是很高效率的了. 首先需要下载该插件: 在File->Setting->Plugins里的搜索框内输入内容:android parcelable code generator,然后自己下载好重启studio即可使用该插件了. 下载插件界面: 重启studio: 点击

  • Android Studio 修改类的默认注释图文教程

    在Android Studio中创建一个类的时候,默认会注释create by- 如果不修改默认注释,AS会给你报一片屎黄色的警告,说你用了默认的文件头模板. 对于有代码洁癖的码农来说,不能忍.于是点击菜单栏的"File"->"Settings",搜索file and code template,选中include-> File Header,按需修改.确定后在创建类就不会注释发生改变,也不会报警告了. 补充知识:Android Studio 修改注释模

  • Android Studio 如何删除/新建一个module(图文教程详解)

    一.删除一个module PS:此方法也会将该module从你的硬盘中删除 如果直接右键会发现没有delete选项 1.选中想要删除的module,右键点击Open Module Settings选项 2.选中移除 3.点击yes 4.注意点击ok 5.小绿点消失说明操作成功啦 6.右键delete 二.新建一个module 1.file-new–new module 2.选择新建的moudle类型 3.编辑应用名称和module名称 4.可直接finish不做修改 附页 1.Android s

随机推荐