Mac下编译FFMpeg(AndroidStudio)

来源:互联网 发布:听知有声小说阅读器 编辑:程序博客网 时间:2024/05/18 13:05

最近想仔细研究一下公司的推流以及播放器的底层代码,可是我是做Java的c不是特别的懂,没有办法,先一步步来吧。
ndk配置其实都很简单,我这里就不赘述了,网上大神的帖子也比较多,其实也就下载安装那么几步,然后这里用到的主要也就是是ndk-build这个命令,我用的是mac系统其他的环境变量的配置大同小异,windows下的可能还需要Cywing。
ffmpeg的下载地址:https://ffmpeg.org/download.html#build-mac
下载完成解压(得到如图不包括android文件夹):
这里写图片描述
配置ndk环境
open ~/.bash_profile 配置环境变量
这里写图片描述
配置ndk(添加ndk的目录位置)
执行source ~/.bash_profile(生效配置)
执行$PATH:如果得到命令行结果里已经包含你配置的ndk路径那就是成功了
这里写图片描述

编译FFMpeg

本文的第一张图里边有一个configure,使用sublime Text打开,其他编辑程序也可以,然后找到如下几行

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

这个主要是生成的lib包的包名规范成以libxxx.so的形式。
然后编写编译脚本 :
编写脚本的时候需要注意windows下可能会有问题:

1.在WIN底下用文本编辑工具修改过参数变量,在保存的时候没注意编码格式造成的,
2.新建一个名为build_android.sh。代码如下:

#!/bin/shNDK=/Users/hejunlin/Downloads/android-ndk-r10eSYSROOT=$NDK/platforms/android-21/arch-armTOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64function 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_FLAGmake cleanmakemake install}CPU=armPREFIX=$(pwd)/android/$CPUADDI_CFLAGS="-marm"build_one

前三行的路径配置,需要跟橘子机的电脑需改,之前配置过NDK应该记得自己的路径吧。
然后在终端上进入build_android.sh所在的文件夹输入./build_android.sh,然后等一段时间,你会发现在FFmpeg中出现了一个名为android的文件夹,格式如下:
这里写图片描述
这样所需要的ffmpeg的so库都做好了提前准备的工作。
接下来导入到项目中:
新建项目——》在src/main下建一个jni目录 ——》把上边编译出来的android的目录放到jni文件加下。
最后的目录应该是这样的,
这里写图片描述
Android.mk的代码:

LOCAL_PATH :=$(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := avcodecLOCAL_SRC_FILES := libavcodec-57.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := avfilterLOCAL_SRC_FILES := libavfilter-6.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := avformatLOCAL_SRC_FILES := libavformat-57.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := avutilLOCAL_SRC_FILES := libavutil-55.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := swresampleLOCAL_SRC_FILES := libswresample-2.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := swscaleLOCAL_SRC_FILES := libswscale-4.soinclude $(PREBUILT_SHARED_LIBRARY)#Programinclude $(CLEAR_VARS)LOCAL_MODULE :=sffhelloworldLOCAL_SRC_FILES := simplest_ffmpeg_helloworld.cLOCAL_C_INCLUDES += $(LOCAL_PATH)/includeLOCAL_LDLIBS := -llog -lzLOCAL_SHARED_LIBRARIES := avcodec avfilter avformat avutil swresample swscaleinclude $(BUILD_SHARED_LIBRARY)

Application.mk这个文件简单的说一下就是需要变异那种平台或格式的so库,我只写了一种情况的,代码特别简单:
这里写图片描述
最后就是C的代码,这个代码是从逆流的鱼的博客上copy的,不过他上边大部分都是图片,为了大家快速上手避免一些不必要的麻烦我自己写了一遍,直接贴代码,注意JNI的签名要用自己的JAVA+包名+类名+方法名,我的代码如下:

#include <stdio.h>#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavfilter/avfilter.h"#ifdef ANDROID#include <jni.h>#include <android/log.h>#define LOGE(format,...) __android_log_print(ANDROID_LOG_ERROR,"myndk",format,##__VA_ARGS__)#else#define LOGE(format,...) printf("(>_<)"format "\n",##__VA_ARGS__)#endifJNIEXPORT jstring Java_com_shenpengliang_sample_ndkdemo_MainActivity_avcodecinfo(JNIEnv *env,jobject obj){    char info[40000] ={0};    av_register_all();    AVCodec *c_temp = av_codec_next(NULL);    while(c_temp != NULL){        if(c_temp->decode!=NULL){            sprintf(info,"%s[Dec]",info);        }else{            sprintf(info,"%s[Enc]",info);        }        switch(c_temp->type){           case AVMEDIA_TYPE_VIDEO:            sprintf(info,"%s[Video]",info);            break;           case AVMEDIA_TYPE_AUDIO:            sprintf(info,"%s[AUDIO]",info);            break;           default:            sprintf(info,"%s[Other]",info);            break;        }        sprintf(info,"%s[%10s]\n",info,c_temp->name);        c_temp=c_temp->next;        LOGE("shenpengliang1");    }    return (*env)->NewStringUTF(env,info);}

然后进入到terminal,cd到jni目录,执行ndk-build,(一般情况下ndk的目录应该在local.properties由系统自动创建了,如果没有收到呢添加)
然后会在lib目录下会生成几个so库,如图:
这里写图片描述
将lib里边的so库拷贝到jniLibs目录下,或者去更改build.gradle的配置文件,将jni指向到lib目录,看个人喜好了。
我的MainActivity的代码是这样的,大家参考吧

import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.TextView;public class MainActivity extends AppCompatActivity {    private TextView textView;    static {        try{            System.loadLibrary("avutil-55");            System.loadLibrary("swresample-2");            System.loadLibrary("avcodec-57");            System.loadLibrary("avformat-57");            System.loadLibrary("swscale-4");            System.loadLibrary("avfilter-6");            System.loadLibrary("sffhelloworld");        }catch(Exception e){            e.printStackTrace();        }    }    public native String avcodecinfo();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        textView= (TextView) findViewById(R.id.test_demo);        textView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                textView.setText(avcodecinfo());            }        });    }}

运行出来的效果图:
这里写图片描述
最近在看Android视频方面的编码,所以有时间和大家一起学习分享,欢迎指正,共同进步,一起向更高的方向进击吧。

0 0