编译ffmpeg

android studio 新建项目,勾选上

将编译好的libffmpeg.so库扔到src/main/jniLibs/armeabi下(主要这里我只编译了arm的ffmpeg的库)

新建文件com.jni.FFmpegCmd

  1. package com.jni;
  2.  
  3. public class FFmpegCmd {
  4.  
  5. static {
  6. System.loadLibrary("ffmpeg");
  7. System.loadLibrary("ffmpeg-cmd");
  8. }
  9.  
  10. public static native int run(String[] commands);
  11.  
  12. }

在cpp下 (即有native-lib.cpp的目录) 创建一个ffmpeg-cmd.cpp文件

  1. #include <jni.h>
  2. #include "ffmpeg.h"
  3. #include "android_log.h"
  4.  
  5. extern "C" JNIEXPORT jint JNICALL
  6. Java_com_jni_FFmpegCmd_run(JNIEnv *env, jobject, jobjectArray commands) {
  7. int argc = env->GetArrayLength(commands);
  8. char *argv[argc];
  9. for (int i = ; i < argc; i++) {
  10. jstring js = (jstring) env->GetObjectArrayElement(commands, i);
  11. argv[i] = (char *) env->GetStringUTFChars(js, );
  12. }
  13. LOGD("============开始执行命令行===========");
  14. return main(argc, argv);
  15. }

android_log.h

  1. #ifdef ANDROID
  2. #include <android/log.h>
  3. #ifndef LOG_TAG
  4. #define MY_TAG "MYTAG"
  5. #define AV_TAG "AVLOG"
  6. #endif
  7. #define LOGE(format, ...) __android_log_print(ANDROID_LOG_ERROR, MY_TAG, format, ##__VA_ARGS__)
  8. #define LOGD(format, ...) __android_log_print(ANDROID_LOG_DEBUG, MY_TAG, format, ##__VA_ARGS__)
  9. #define XLOGD(...) __android_log_print(ANDROID_LOG_INFO,AV_TAG,__VA_ARGS__)
  10. #define XLOGE(...) __android_log_print(ANDROID_LOG_ERROR,AV_TAG,__VA_ARGS__)
  11. #else
  12. #define LOGE(format, ...) printf(MY_TAG format "\n", ##__VA_ARGS__)
  13. #define LOGD(format, ...) printf(MY_TAG format "\n", ##__VA_ARGS__)
  14. #define XLOGE(format, ...) fprintf(stdout, AV_TAG ": " format "\n", ##__VA_ARGS__)
  15. #define XLOGI(format, ...) fprintf(stderr, AV_TAG ": " format "\n", ##__VA_ARGS__)
  16. #endif

拷贝ffmpeg源码文件 cmdutils.c cmdutils.h ffmpeg.cffmpeg_filter.cffmpeg_opt.c ffmpeg_hw.c 到cpp目录下

(ffmpeg-3.4之前的版本 不需要ffmpeg_hw.c文件,但是需要cmdutils_common_opts.h文件)

ffmpeg编译后的文件夹include lib也拷贝到该目录

修改ffmpeg.h 在最后添加    int main(int argc, char **argv);

修改ffmpeg.c

在main方法最后添加(听说是为了防止为了重复执行ffmpeg命令闪退问题)

  1. nb_filtergraphs = ;
  2. progress_avio = NULL;
  3.  
  4. input_streams = NULL;
  5. nb_input_streams = ;
  6. input_files = NULL;
  7. nb_input_files = ;
  8.  
  9. output_streams = NULL;
  10. nb_output_streams = ;
  11. output_files = NULL;
  12. nb_output_files = ;
  1. 修改cmdutils.h
  1. 修改前 void exit_program(int ret) av_noreturn;
  2. 修改后 int exit_program(int ret);
  3.  
  4. 修改前 void show_help_children(const AVClass *class, int flags);//不修改的话编译一直出错 (可能是class关键字的原因,关键字不能当变量使用)
  5. 修改后 void show_help_children(const AVClass *avClass, int flags);

修改cmdutils.c

  1. 修改前
  2. void exit_program(int ret)
  3. {
  4. if (program_exit)
  5. program_exit(ret);
  6.  
  7. exit(ret);
  8. }
  9. 修改后
  10. int exit_program(int ret)
  11. {
  12. if (program_exit)
  13. program_exit(ret);
  14.  
  15. return ret;
  16. }

CMakeLists.txt

  1. cmake_minimum_required(VERSION 3.4.)
  2.  
  3. add_library(ffmpeg-cmd
  4. SHARED
  5. src/main/cpp/cmdutils.c
  6. src/main/cpp/ffmpeg.c
  7. src/main/cpp/ffmpeg_filter.c
  8. src/main/cpp/ffmpeg_opt.c
  9. src/main/cpp/ffmpeg_hw.c
  10. src/main/cpp/ffmpeg-cmd.cpp)
  11.  
  12. find_library(log-lib
  13. log
  14. android)

  15. #这里红色部分对应上面拷贝的两个文件夹路径,这里也可以不用拷贝这两个文件夹,直接把下面两行红色部分给成你电脑上编译好的ffmpeg的include和lib的路径
  16. include_directories(src/main/cpp/include
  17. src/main/cpp/lib
  18. E:/ffmpeg/4.0/build/ffmpeg-4.0)
  19. add_library(ffmpeg SHARED IMPORTED)
  20. set_target_properties(ffmpeg PROPERTIES IMPORTED_LOCATION E:/ffmpeg/4.0/build/android/arm/libffmpeg.so)
  21.  
  22. target_link_libraries(
  23. ffmpeg-cmd
  24. ffmpeg
  25. android
  26. ${log-lib} )

build.gradle(Module:app)

这里主要需要处理红色圈圈部分,其他部分都是自动生成的

最后在MainActivity.java 测试一下

  1. public class MainActivity extends AppCompatActivity {
  2.  
  3. private ExecutorService es = Executors.newSingleThreadExecutor();
  4. String path = Environment.getExternalStorageDirectory().getPath();
  5.  
  6. private static final int REQUEST_EXTERNAL_STORAGE = 1;
  7. private static String[] PERMISSIONS_STORAGE = {
  8. "android.permission.READ_EXTERNAL_STORAGE",
  9. "android.permission.WRITE_EXTERNAL_STORAGE" };
  10.  
  11. private ProgressDialog progressDialog;
  12. private TextView tv;
  13.  
  14. @Override
  15. protected void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.activity_main);
  18. try {
  19. //检测是否有写的权限
  20. int permission = ActivityCompat.checkSelfPermission(activity,
  21. "android.permission.WRITE_EXTERNAL_STORAGE");
  22. if (permission != PackageManager.PERMISSION_GRANTED) {
  23. // 没有写的权限,去申请写的权限,会弹出对话框
  24. ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
  25. }
  26. } catch (Exception e) {
  27. e.printStackTrace();
  28. }
  29.  
  30. tv = findViewById(R.id.sample_text);
  31. tv.setText("测试");
  32.  
  33. tv.setOnClickListener(new View.OnClickListener() {
  34. @Override
  35. public void onClick(View v) {
  36. progressDialog = ProgressDialog.show(MainActivity.this,"","处理中");
  37. new Thread(new Runnable() {
  38. @Override
  39. public void run() {
  40. String str = "ffmpeg -i %s -vcodec copy -f mpegts -y %s";//mp4 转 ts -y如果有同名名则覆盖文件。不加-y则会提示有同名文件是否覆盖,这里再次执行的话会闪退
  41. String commandStr = String.format(str,path+"/data/qq.mp4",path+"/data/qq.ts");
  42. String[] commands = commandStr.split("\\s+");
  43. for(String command:commands){
  44. Log.d(MainActivity.class.getName(),"command="+command);
  45. }
  46. final int sum = FFmpegCmd.run(commands);
  47.  
  48. new Handler(Looper.getMainLooper()).post(new Runnable() {
  49. @Override
  50. public void run() {
  51. if(sum == 0){
  52. if(progressDialog != null){
  53. progressDialog.dismiss();
  54. }
  55. tv.setText("处理成功");
  56. }else{
  57. tv.setText("处理失败");
  58. }
  59. }
  60. });
  61. }
  62. }).start();
  63. }
  64. });
  65. }
  66.  
  67. }

AndroidManifest.xml 需要添加权限

  1. <!--网络连接-->
  2. <uses-permission android:name="android.permission.INTERNET" />
  3. <!--sd卡读写 6.0以上系统可能还需要动态申请sd卡读写权限-->
  4. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  5. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

android studio ffmpeg简单使用 (cmake)的更多相关文章

  1. Android Studio IDE 简单学习和介绍

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  2. 通过android studio的gradle强制cmake输出命令详情

    https://stackoverflow.com/questions/43439549/force-cmake-in-verbose-mode-via-gradle-and-the-android- ...

  3. Android Studio 超级简单的打包生成apk

    为什么要打包: apk文件就是一个包,打包就是要生成apk文件,有了apk别人才能安装使用.打包分debug版和release包,通常所说的打包指生成release版的apk,release版的apk ...

  4. Android Studio一些简单设置

          简单设置   1.默认主题设置 默认的 Android Studio 为灰色界面,能够选择使用炫酷的黑色界面. Settings --> Appearance --> Them ...

  5. android studio 2.2 使用cmake编译NDK

    Android studio 2.2 已经进入beta版本,新功能添加众多,NDK编程也得到了简化.官方博客介绍.本文介绍如何使用新版android studio调用 c++代码,为了超级通俗易懂,例 ...

  6. Android Studio的简单设置:

    4.关闭更新: 如下图所示: 6.添加api文档悬浮提示: AS默认是没有api文档悬浮提示的,只有按住[Ctrl+Q]太会出现提示.如果要添加api的自动悬浮提示,设置如下: 上图中,在红框部分打钩 ...

  7. 在Android Studio进行“简单配置”单元测试(Android Junit)

    起因 在Android studio 刚出.本人就想弄单元测试,可惜当时Android studio不知道抽什么风(准确来说,应该是我不会弄而已).无法执行到相应的代码.后来今天突然自己又抽风.又想去 ...

  8. 重大发现Android studio 如何简单快速修改package name

    好多人都发现Android studio修改包名比较麻烦,只能一级一级的修改,今天偶尔发现了一个快捷方法. 废话不多说: 1 打开项目的AndroidManifest.xml文件 2 鼠标光笔定位到你 ...

  9. Android studio实现简单的CRUD

    1.打开Android studio ,创建项目DataBase01 2.进行UI设计,如图 目的:实现对姓名及其爱好的增删改查 3.创建DB.java,用于创建数据库,并做相关操作 在该目录下右键- ...

随机推荐

  1. ZOJ - 3954 Seven-Segment Display 【状态标记】

    题目链接 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3954 题意 有一块 LED 灯 然后上面有七块灯管 在显示不同数 ...

  2. html video api控件总结

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. 转回java,项目遇到的环境相关问题记录

    fastjson解析报错,兼容java8的time包:需要升级fastjson版本到1.2.9 https://www.oschina.net/question/129411_142776     j ...

  4. Protobuf入门实例

    Protobuf是一个灵活.高效.结构化的数据序列化框架,相比于XML等传统的序列化工具, 它更小.更快.更简单.Protobuf支持数据结构化一次就可以到处使用,甚至是跨语言使用,通过代码生成工具可 ...

  5. UVA-10534 (LIS)

    题意: 给定一个长为n的序列,求一个最长子序列,使得该序列的长度为2*k+1,前k+1个数严格递增,后k+1个数严格单调递减; 思路: 可以先求该序列最长单调递增和方向单调递增的最长序列,然后枚举那第 ...

  6. Python:条件判断

    条件控制:if...elif...else if condition_1: statement_1 elif condition_2: statement_2 else: statement_3 判断 ...

  7. bzoj 3809 Gty的二逼妹子序列——莫队+分块

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3809 容易想到树状数组维护值域.但修改和查询都是 log 太慢. 考虑有 nsqrt(n) ...

  8. poj2828 Buy Tickets——倒序处理

    题目:http://poj.org/problem?id=2828 这题可以倒序来做,因为越靠后的人实际上优先级越高: 用0和1表示这个位置上是否已经有人,0表示有,1表示没有,这样树状数组维护前缀和 ...

  9. mysql分区表之四:分区表性能

    一,      分区概念  分区允许根据指定的规则,跨文件系统分配单个表的多个部分.表的不同部分在不同的位置被存储为单独的表.MySQL从5.1.3开始支持Partition. 分区和手动分表对比 手 ...

  10. CS231n 2016 通关 第三章-SVM 作业分析

    作业内容,完成作业便可熟悉如下内容: cell 1  设置绘图默认参数 # Run some setup code for this notebook. import random import nu ...