编译Android下可执行命令的FFmpeg
请尊重原创,转载请注明出处:http://blog.csdn.net/mabeijianxi/article/details/72904694
本人环境与工具:
- ndk:r14
- FFmpeg版本: 3.2.5
- Android Studio: 2.3.2
一、说明:
本文是经过实战总结出的经验,本文将用两种方式编译可以在Android下执行命令的FFmpeg,一种是传统的ndk-build工具,一种是cmake工具,经过我的项目实战,非常推荐cmake,因为AS 2.2以后对它支持的非常好,你可以非常方便的像debug Java代码一样去debug Native代码。本文以是在假设已经编译好了全架构的 FFmpeg 的基础上进行的,编译步骤: 编译Android下可用的全平台FFmpeg(包含libx264与libfdk-aac)。
二、传统ndk-build命令编译
所谓传统,必然就稍微没那么智能了,我们一步一步的搞。
- 打开你养家糊口的Android Studio,娴熟的新建一个项目;
编写一个 native 函数,如果只是测试我们在MainActivity里面搞就行了:
public native int ffmpegRun(String[] cmd);
新建jni目录,在目录下新建文件: jx_ffmpeg_cmd_run.c;
编码对应的 JNI 接口:
#include <jni.h><br> JNIEXPORT jint JNICALL Java_com_mabeijianxi_jianxiffmpegcmd_MainActivity_ffmpegRun(JNIEnv *env, jobject instance, jobjectArray cmd) {// TODO }
找到我们FFmpeg编译后的根目录,然后 copy:
cmdutils.c cmdutils.h cmdutils_common_opts.h config.h ffmpeg.c ffmpeg.h ffmpeg_filter.c ffmpeg_opt.c(注意需要编译后才会有config.h)到 jni 目录下,再进入到我们的编译后的产物目录,把include文件夹与所有的 .so 动态库也 copy 到jni目录下。完成后你jni目录结构应该如下图:文件修改
修改ffmpeg.c与ffmpeg.h
找到ffmpeg.c,把int main(int argc, char argv) 改名为 int jxRun(int argc, char argv)
找到ffmpeg.h, 在文件末尾添加函数申明: int jxRun(int argc, char **argv);1)修改cmdutils.c 和 cmdutils.h
找到cmdutils.c中的exit_program函数
修改前:修改后:
2)找到cmdutils.h中exit_program的申明,也把返回类型修改为int。
修改前:修改后:
很多教程都只修改到这里,基本没什么问题,但是你实际运行的时候会发现如果连续多次执行命令会有问题的,通过源码我们可以知道,FFmpeg每次执行完命令后会调用 ffmpeg_cleanup 函数清理内存,并且会调用exit(0)结束当前进程,但是经过我们的修改,exit()的代码已经被删掉,我们在Android中自然不能结束当前进程了,所以有些变量的值还在内存中,这样就会导致下次执行的时候可能会出错。我也尝试过fork一个进程给ffmpeg执行,完事后通过 信号来进程间通信,这样管用但是很麻烦,我们其实只需要简单的重设一些变量即可。
打开ffmpeg.c找到刚修改的jxRun函数,然后在 return 前加上如下代码即可:nb_filtergraphs = 0;progress_avio = NULL;input_streams = NULL;nb_input_streams = 0;input_files = NULL;nb_input_files = 0;output_streams = NULL;nb_output_streams = 0;output_files = NULL;nb_output_files = 0;
编写调用函数
我们上面只在jx_ffmpeg_cmd_run.c新建了一个JNI接口函数,还没有实现逻辑,我们实现后的代码如下:** * Created by jianxi on 2017/6/4. * https://github.com/mabeijianxi * mabeijianxi@gmail.com * #include "ffmpeg.h" #include <jni.h> JNIEXPORT jint JNICALL Java_com_mabeijianxi_jianxiffmpegcmd_MainActivity_ffmpegRun(JNIEnv *env, jobject type,jobjectArray commands){int argc = *env)->GetArrayLength(env,commands);char *argv[argc];int i;for (i = 0; i < argc; i++) {jstring js = (jstring) (*env)->GetObjectArrayElement(env,commands, i);argv[i] = (char *) (*env)->GetStringUTFChars(env,js, 0);}return jxRun(argc,argv); }
- 编写Application.mk与Android.mk
1)在jni目录下新建Application.mk与Android.mk
2)编写Application.mk,内容如下:APP_ABI := armeabi-v7a APP_PLATFORM := android-14
3)编码Android.mk,其内容如下(不明含义的可看Android下玩JNI的新老三种姿势
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)
LOCAL_MODULE := libavcodec
LOCAL_SRC_FILES := libavcodec.so
include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)
LOCAL_MODULE := libavfilter
LOCAL_SRC_FILES := libavfilter.so
include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)
LOCAL_MODULE := libavformat
LOCAL_SRC_FILES := libavformat.so
include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)
LOCAL_MODULE := libavutil
LOCAL_SRC_FILES := libavutil.so
include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)
LOCAL_MODULE := libswresample
LOCAL_SRC_FILES := libswresample.so
include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)
LOCAL_MODULE := libswscale
LOCAL_SRC_FILES := libswscale.so
include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)
LOCAL_MODULE := jxffmpegrun
LOCAL_SRC_FILES := cmdutils.c ffmpeg.c ffmpeg_filter.c ffmpeg_opt.c jx_ffmpeg_cmd_run.c# 这里的地址改成自己的 FFmpeg 源码目录
LOCAL_C_INCLUDES :=/Users/jianxi/Downloads/code/ffmpeg-3.2.5
LOCAL_LDLIBS := -llog -lz -ldl
LOCAL_SHARED_LIBRARIES :=libavcodec libavfilter libavformat libavutil libswresample libswscale
include $(BUILD_SHARED_LIBRARY)
9. 开始编译:
我们打开终端,然后cd 到jni目录下,然后执行ndk-build,如果你没配置其环境变量,你选择写入ndk-build的全路径。
如果顺利你可以在命令结束后看到如下输出:
![](http://upload-images.jianshu.io/upload_images/5461213-4aeec7c7ad04cb12.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
并且你的lib下会有如下产物:
![](http://upload-images.jianshu.io/upload_images/5461213-5f944929a009531e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
这里就先不上测试的效果图了,等后面一起搞
三、cMake编译
有好多步骤都是很上面一样的,一会儿我就快乐的copy下来哈
- 打开你养家糊口的Android Studio,版本最好大于2.2,很关键。娴熟的新建一个项目,但是与以往不同,你最好勾选上 C++ 支持与 C++ standard选项时选择 C++ 11,如下图:
新建完成后你会发现帮你生成好了接口,这时我们只需修改native函数即可:
修改前:public native String stringFromJNI();
修改后
public native int ffmpegRun(String[] cmd);
修改native文件与函数:
你会发现这时多了一个cpp的文件夹,里面多了一个native-lib.cpp的文件,我们修改其名为jx_ffmpeg_cmd_run.c,然后修改里面的函数,修改后的函数应该如下:#include <jni.h> JNIEXPORT jint JNICALL Java_com_mabeijianxi_jianxiffmpegcmd_MainActivity_ffmpegRun(JNIEnv *env, jobject instance, jobjectArray cmd) {// TODO }
- 找到我们FFmpeg编译后的根目录,然后 copy:
cmdutils.c cmdutils.h cmdutils_common_opts.h config.h ffmpeg.c ffmpeg.h ffmpeg_filter.c ffmpeg_opt.c(注意需要编译后才会有config.h)到 cpp 目录下,再进入到我们的编译后的产物目录,把include文件夹 copy 到cpp目录下。完成后你cpp目录结构应该如下图:
![](http://upload-images.jianshu.io/upload_images/5461213-e70c07542868ddf7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
文件修改
修改ffmpeg.c与ffmpeg.h
找到ffmpeg.c,把int main(int argc, char argv) 改名为 int jxRun(int argc, char argv)
找到ffmpeg.h, 在文件末尾添加函数申明: int jxRun(int argc, char **argv);1)修改cmdutils.c 和 cmdutils.h
找到cmdutils.c中的exit_program函数
修改前:修改后:
2)找到cmdutils.h中exit_program的申明,也把返回类型修改为int。
修改前:修改后:
很多教程都只修改到这里,基本没什么问题,但是你实际运行的时候会发现如果连续多次执行命令会有问题的,通过源码我们可以知道,FFmpeg每次执行完命令后会调用 ffmpeg_cleanup 函数清理内存,并且会调用exit(0)结束当前进程,但是经过我们的修改,exit()的代码已经被删掉,我们在Android中自然不能结束当前进程了,所以有些变量的值还在内存中,这样就会导致下次执行的时候可能会出错。我也尝试过fork一个进程给ffmpeg执行,完事后通过 信号来进程间通信,这样管用但是很麻烦,我们其实只需要简单的重设一些变量即可。
打开ffmpeg.c找到刚修改的jxRun函数,然后在 return 前加上如下代码即可:nb_filtergraphs = 0;progress_avio = NULL;input_streams = NULL;nb_input_streams = 0;input_files = NULL;nb_input_files = 0;output_streams = NULL;nb_output_streams = 0;output_files = NULL;nb_output_files = 0;
编写调用函数
我们上面只在jx_ffmpeg_cmd_run.c新建了一个JNI接口函数,还没有实现逻辑,我们实现后的代码如下:\** \* Created by jianxi on 2017/6/4. \* https://github.com/mabeijianxi \* mabeijianxi@gmail.com */ #include "ffmpeg.h" #include <jni.h> JNIEXPORT jint JNICALL Java_com_mabeijianxi_jianxiffmpegcmd_MainActivity_ffmpegRun(JNIEnv *env, jobject type,jobjectArray commands){int argc = (*env)->GetArrayLength(env,commands);char *argv[argc];int i;for (i = 0; i < argc; i++) {jstring js = (jstring) (*env)->GetObjectArrayElement(env,commands, i);argv[i] = (char *) (*env)->GetStringUTFChars(env,js, 0);}return jxRun(argc,argv); }
- 编写cmake编译脚本:
在没有编写脚本的时候你的代码应该是一片红,没关系,马上我们就干掉它。
打开你当前Module下的CMakeLists.txt然后填写如下脚本(内容解释可看Android下玩JNI的新老三种姿势):
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html# Sets the minimum version of CMake required to build the native library.cmake_minimum_required(VERSION 3.4.1)# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.add_library( # Sets the name of the library.jxffmpegrun# Sets the library as a shared library.SHARED# Provides a relative path to your source file(s).src/main/cpp/cmdutils.csrc/main/cpp/ffmpeg.csrc/main/cpp/ffmpeg_filter.csrc/main/cpp/ffmpeg_opt.csrc/main/cpp/jx_ffmpeg_cmd_run.c)
add_library(avcodecSHAREDIMPORTED)add_library(avfilterSHAREDIMPORTED)add_library(avformatSHAREDIMPORTED)add_library(avutilSHAREDIMPORTED)add_library(swresampleSHAREDIMPORTED)add_library(swscaleSHAREDIMPORTED)add_library(fdk-aacSHAREDIMPORTED)if(${ANDROID_ABI} STREQUAL "armeabi")
set_target_properties(avcodecPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libavcodec.so)set_target_properties(avfilterPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libavfilter.so)set_target_properties(avformatPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libavformat.so)set_target_properties(avutilPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libavutil.so)set_target_properties(swresamplePROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libswresample.so)set_target_properties(swscalePROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libswscale.so)set_target_properties(fdk-aacPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libfdk-aac.so)
endif(${ANDROID_ABI} STREQUAL "armeabi")if(${ANDROID_ABI} STREQUAL "armeabi-v7a")set_target_properties(avcodecPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavcodec.so)set_target_properties(avfilterPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavfilter.so)set_target_properties(avformatPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavformat.so)set_target_properties(avutilPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavutil.so)set_target_properties(swresamplePROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libswresample.so)set_target_properties(swscalePROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libswscale.so)set_target_properties(fdk-aacPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libfdk-aac.so)endif(${ANDROID_ABI} STREQUAL "armeabi-v7a")if(${ANDROID_ABI} STREQUAL "arm64-v8a")
set_target_properties(avcodecPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libavcodec.so)set_target_properties(avfilterPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libavfilter.so)set_target_properties(avformatPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libavformat.so)set_target_properties(avutilPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libavutil.so)set_target_properties(swresamplePROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libswresample.so)set_target_properties(swscalePROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libswscale.so)set_target_properties(fdk-aacPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libfdk-aac.so)
endif(${ANDROID_ABI} STREQUAL "arm64-v8a")if(${ANDROID_ABI} STREQUAL "x86")
set_target_properties(avcodecPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavcodec.so)set_target_properties(avfilterPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavfilter.so)set_target_properties(avformatPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavformat.so)set_target_properties(avutilPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavutil.so)set_target_properties(swresamplePROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libswresample.so)set_target_properties(swscalePROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libswscale.so)set_target_properties(fdk-aacPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libfdk-aac.so)
endif(${ANDROID_ABI} STREQUAL "x86")if(${ANDROID_ABI} STREQUAL "x86_64")
set_target_properties(avcodecPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libavcodec.so)set_target_properties(avfilterPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libavfilter.so)set_target_properties(avformatPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libavformat.so)set_target_properties(avutilPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libavutil.so)set_target_properties(swresamplePROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libswresample.so)set_target_properties(swscalePROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libswscale.so)set_target_properties(fdk-aacPROPERTIES IMPORTED_LOCATION${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libfdk-aac.so)
endif(${ANDROID_ABI} STREQUAL "x86_64")include_directories(/Users/jianxi/Downloads/code/ffmpeg-3.2.5/)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.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 )# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.target_link_libraries( # Specifies the target library.jxffmpegrunfdk-aacavcodecavfilteravformatavutilswresampleswscale# Links the target library to the log library# included in the NDK.${log-lib} )
当然你还需要修改脚本里面的一些文件路径。
8 . 修改当前Module下的build.gradle脚本:
我所谓的全架构其实是排除了 mips 的,觉得没什么卵用,所以我们还需要添加过滤:
修改前:
![](http://upload-images.jianshu.io/upload_images/5461213-82ce351159e66348.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
修改后:
![](http://upload-images.jianshu.io/upload_images/5461213-792f9511f690d0fd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
做到这步我们就可以直接点击同步按钮了:
![](http://upload-images.jianshu.io/upload_images/5461213-9a968ddd3a37914d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
完成后就不会再爆红了,这时候是只能直接运行安装的,但是还没有输入命令,所以没什么意义,接下来将开始使用我们做好的工具。
四、测试与使用
我们要用动态库肯定得放入默认目录,或者在gradle.build中修改其路径,这里我就直接放入
jniLibs 里面了,如图:
![](http://upload-images.jianshu.io/upload_images/5461213-d2692904a3e76741.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
然后我就是在java里面调用了,搞了一个进度条,一个按钮。没有什么技术含量,直接贴代码了哈:
public class MainActivity extends AppCompatActivity {static {System.loadLibrary("jxffmpegrun");System.loadLibrary("avcodec");System.loadLibrary("avformat");System.loadLibrary("avutil");System.loadLibrary("swscale");System.loadLibrary("fdk-aac");}private ProgressBar pb;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);pb = (ProgressBar) findViewById(R.id.pb);}public void onClick(View v){pb.setVisibility(View.VISIBLE);new Thread(new Runnable() {@Overridepublic void run() {String basePath = Environment.getExternalStorageDirectory().getPath();String cmd_transcoding = String.format("ffmpeg -i %s -c:v libx264 %s -c:a libfdk_aac %s",basePath+"/"+"girl.mp4","-crf 40",basePath+"/"+"my_girl.mp4");int i = jxFFmpegCMDRun(cmd_transcoding);new Handler(Looper.getMainLooper()).post(new Runnable() {@Overridepublic void run() {pb.setVisibility(View.GONE);Toast.makeText(MainActivity.this,"ok了",Toast.LENGTH_SHORT).show();}});}}).start();}public int jxFFmpegCMDRun(String cmd){String regulation="[ \\t]+";final String[] split = cmd.split(regulation);return ffmpegRun(split);}public native int ffmpegRun(String[] cmd);
}
再上面代码中我们指定编码器压缩了一个mp4的文件,压缩前叫girl.mp4,压缩后叫my_girl.mp4,如图所示,我们发现其缩小了近80%。
![](http://upload-images.jianshu.io/upload_images/5461213-ad847357addaf363.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
五、总结
这里输入路径不能每次是同一个,不然会报错,也就是说,运行了一次上面的命令后,输出的名字不能再叫my_girl.mp4了,你可以叫your_girl.mp4。然后还是那句话推荐用cMake,你看我们通过cMake编译可以直接debug native
![](http://upload-images.jianshu.io/upload_images/5461213-ac93a625290b003b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
是不是很hi,然后我们在开发中可能会发现有些命令执行不了,这时候你首先需要检查命令,然后确保没问题后,你需要确定你在编译FFmpeg的时候是否开启了此功能,很关键,确定办法很简单,一是检查FFmpeg的编译脚本,二是通过FFmpeg的函数获取编译信息,我工程里面已经内含这个jni接口,有兴趣的基友可以下载来try一try。如果有兴趣进一步探索FFmpeg在Android上的实战运用,可以看我的开源项目和其讲解博客,分别是:https://github.com/mabeijianxi/small-video-record、利用FFmpeg玩转Android视频录制与压缩(一)、利用FFmpeg玩转Android视频录制与压缩(二)。
本文所有源码地址:https://github.com/mabeijianxi/FFmpeg4Android
编译Android下可执行命令的FFmpeg相关推荐
- 编译Android下可用的全平台FFmpeg(包含libx264与libfdk-aac)
请尊重原创,转载请注明出处:http://blog.csdn.net/mabeijianxi/article/details/74544879 源码或工具版本: ndk :r14 FFmpeg 版本: ...
- python编译exe文件太大了_python编译windows下可执行的exe文件
python编译windows下可执行的exe文件的操作流程: 1.在安装python环境的windows下,安装 pyinstaller,请在dos下执行如下命令: pip install pyin ...
- java test abc_DOS命令行下成功执行命令:java Test abc 21,则以下描述正确的是()
[单选题]假设有两个整数x和y,表达式x>=y?x:y的含义是() [单选题]下列哪项不是Java语言的关键字?() [判断题]每项经济业务发生后,都会引起企业的资产和权益总额发生增减变动,但会 ...
- 安卓和Linux动态库一样吗,在Linux环境下编译Android下的最新版ffmpeg+x264单个动态库(.so)...
最近在mac下用ndk交叉编译最ffmpeg出问题,总是显示用系统的gcc而不是ndk的toolchain的交叉编译gcc来编译的.之前明明没问题的,可能是由于最近升级macOS导致的.由于对这方面实 ...
- android 命令kill进程号,一定是我打开的姿势不对——Android下使用kill命令杀死指定进程...
环境:Android 5.1.1(已root) 最近有一个需求,需要在Android下杀死指定pid的进程.Android原生API提供了几个接口: (1)android.os.Process.kil ...
- mac下编译android下libaac,Mac系统下编译FFmpeg(支持libx264)for iOS
前言 iOS平台的FFmpeg(支持libx264)已经编译完成.经过之前Android平台上的编译过程,iOS平台的编译总体来说少走了很多弯路,但还是遇到了一些问题,现在做一下总结. 一.编译x26 ...
- 在linux下编译android下的opencv,使用cmake的方法
#前一篇帖子实验了build_sdk.py来编译opencv,失败了. #本篇尝试使用cmake来编译 #感谢这篇帖子提供的指导:https://www.cnblogs.com/jojodru/p/1 ...
- Android下的 iptables命令的用法
netfilter/iptables(简称为iptables)组成Linux平台下的包过滤防火墙,与大多数的Linux软件一样,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火墙解决方案,完成封包过 ...
- android studio 退出编译,Android studio用什么命令可以退出当前应用
最佳答案 Android Studio 启动速度优化1.开启 gradle 单独的守护进程当 Android Studio 遇到错误的时候,往往会导致 Android Studio 挂掉,为了防止退出 ...
最新文章
- 算法工程师当前选哪个方向好?
- iOS10 UI教程管理层次结构
- 图像处理之ROI区域裁剪
- Spark之GraphX
- 为什么坐飞机时会耳痛?
- Azure Cosmos DB从零到10分钟
- html css 圆形按钮 仿uc,10款基于jquery的web前端动画特效
- java 手势识别_【人体分析-手势识别】-Java示例代码
- LSTM 文本分类模型的实现
- 详细安装WIN 10纯净版(虚拟机安装、真机笔记本安装)
- c3300 京瓷km5050_京瓷复印机通用维修代码2
- C语言打印输出图形(初版)
- 不踩雷不将就 京东智能产品30天无忧退
- gps串口通信程序c语言,stm32单片机串口接收GPS数据并解析NMEA之GPRMC
- 科技大停滞--过去已逝,未来未来
- Win7系统电脑调节屏幕亮度的几种方法。
- 学硕上几年学计算机,研究生一般要读几年毕业
- spring配置与监听mysql_spring boot (8)mybatis配置监听,
- w7电脑蓝屏怎么解决_详解win7电脑蓝屏怎么办
- 2020年下半年教育热点事件舆情分析研判报告整合
热门文章
- Java实现简单的个人网络嗅探器
- EPSON 4750 打印机清理
- 面试太诚实居然被淘汰?真的不公平!
- 服务器mtbf性能测试,云服务器 MTBF指标
- 如何实现消息通知系统
- GET http://localhost:8080/api/getArticle 504 (Gateway Timeout) 或者404错误
- 终于有大佬把计算机底层原理全部总结出来了
- java(中国邮政储蓄银行个人网上银行系统项目实训)
- 面试阿里,HashMap 这一篇就够了
- A*算法(五):在三维地图的可行性