我们今天的目标是仿照雷神的博客(https://blog.csdn.net/leixiaohua1020/article/details/47008825),把这个APP写出来,先上图:

APP中有5个按钮,点击不同的按钮,会有不同的ffmpeg信息显示出来,分别是我们编译的ffmpeg所支持的协议,编解码器,过滤器,格式和配置等。

1. 新建Android Studio工程,参照上一篇文章的详细介绍。

2. 在app/src/main/下新建一个jniLibs目录,并将ffmpeg的lib库和include文件夹拷贝过来。

3. 修改CMakeLists.txt文件,与上一篇的一致,以后都使用的是这个CMakList.txt文件,如下所示:


#CMake版本信息
cmake_minimum_required(VERSION 3.4.1)#ffmpeg so文件路径
set(lib_src_DIR ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI})#配置加载native依赖
include_directories(${CMAKE_SOURCE_DIR}/src/main/jniLibs/include)#动态方式加载ffmepg的so文件 第三方库加载方式
add_library(ffmpeg SHARED IMPORTED)#引入libffmpeg.so文件
set_target_properties(ffmpeg PROPERTIES IMPORTED_LOCATION
${lib_src_DIR}/libffmpeg.so)#CPP文件夹下待编译的c文件
add_library(native-lib SHARED ${CMAKE_SOURCE_DIR}/src/main/cpp/native-lib.cpp)#C 日志 ndk官方库
find_library(log-lib log)#静态库与动态库进行链接 相当于gcc命令行参数 -l。
target_link_libraries(native-libandroidffmpeg${log-lib})

4. 修改app/src/build.gradle文件,添加ndk选项,参照上篇。

5. APP的界面是5个按钮和一个显示文字的TextView,修改app/src/main/res/layout/activity_main.xml文件,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><LinearLayoutandroid:id="@+id/linear_layout"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:id="@+id/button_protocol"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="onButtonClick"android:text="@string/button_protocol"android:textSize="12sp"/><Buttonandroid:id="@+id/button_codec"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="onButtonClick"android:text="@string/button_codec"android:textSize="12sp"/><Buttonandroid:id="@+id/button_filter"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="onButtonClick"android:text="@string/button_filter"android:textSize="12sp"/><Buttonandroid:id="@+id/button_format"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="onButtonClick"android:text="@string/button_format"android:textSize="12sp"/><Buttonandroid:id="@+id/button_configuration"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="onButtonClick"android:text="@string/button_configuration"android:textSize="12sp"/></LinearLayout><ScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_below="@+id/linear_layout"android:padding="16dp"><TextViewandroid:id="@+id/sample_text"android:layout_width="match_parent"android:textSize="24sp"android:textColor="#ff0000"android:layout_height="wrap_content"/></ScrollView></RelativeLayout>

同时,这个layout文件中使用了的一些变量需要在app/src/main/res/values/strings.xml里面定义,如下所示:

<resources><string name="app_name">ffmpeg_android_demo_2</string><string name="button_protocol">Protocol</string><string name="button_codec">Codec</string><string name="button_filter">Filter</string><string name="button_format">Format</string><string name="button_configuration">Configuration</string>
</resources>

在做这一步操作时,当切换到app/src/main/res/layout/activity_main.xml的Design视图时,向里面拖拽Button,没有显示,同时提示Render problem,如下所示:

解决办法是找到app/src/main/res/values/styles.xml文件,在Theme前面添加个Base字符,如图所示:

6. 这时候就可以写我们的主程序了,打开app/src/main/java/xxx/MainActivity文件,主要目的就是复写onButtonClick方法,每当点击按钮时,就显示按钮所对应的内容,所以这个函数很好写,只需要设置TextView的显示内容即可,如下所示:

package com.example.nxf31081.ffmpeg_android_demo_2;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;public class MainActivity extends AppCompatActivity {// Used to load the 'native-lib' library on application startup.static {System.loadLibrary("native-lib");}private TextView mTextView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// Example of a call to a native methodmTextView = (TextView) findViewById(R.id.sample_text);}public void onButtonClick(View view) {int id = view.getId();switch (id) {case R.id.button_protocol:mTextView.setText(avProtocolInfo());break;case R.id.button_codec:mTextView.setText(avCodecInfo());break;case R.id.button_filter:mTextView.setText(avFilterInfo());break;case R.id.button_format:mTextView.setText(avFormatInfo());break;case R.id.button_configuration:mTextView.setText(avConfigurationInfo());break;}}/*** A native method that is implemented by the 'native-lib' native library,* which is packaged with this application.*/public native String avProtocolInfo();public native String avFormatInfo();public native String avCodecInfo();public native String avFilterInfo();public native String avConfigurationInfo();
}

7. 重点还是这几个native函数,根据上篇中的介绍,分别生成这个native函数的函数模板,在native-lib.cpp函数中,这几个函数就是ffmpeg API的简单应用了,如下所示:

#include <jni.h>
#include <string>
#include <android/log.h>#define LOG_TAG "FFNative"
#define ALOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
#define ALOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#define ALOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
#define ALOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
#define ALOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libswscale/swscale.h>JNIEXPORT jstring JNICALL
Java_com_example_nxf31081_ffmpeg_1android_1demo_12_MainActivity_avProtocolInfo(JNIEnv *env,jobject instance) {char info[40000] = {0};av_register_all();void *opaque = NULL;const char *name;//Inputwhile((name = avio_enum_protocols(&opaque, 0)))sprintf(info, "%s[Input] : [%10s] \n", info, name);//Outputopaque = NULL;while((name = avio_enum_protocols(&opaque, 1)))sprintf(info, "%s[Output] : [%10s] \n", info, name);return env->NewStringUTF(info);
}JNIEXPORT jstring JNICALL
Java_com_example_nxf31081_ffmpeg_1android_1demo_12_MainActivity_avFormatInfo(JNIEnv *env, jobject instance) {char info[40000] = {0};av_register_all();AVInputFormat *if_temp = av_iformat_next(NULL);AVOutputFormat *of_temp = av_oformat_next(NULL);while (if_temp != NULL) {sprintf(info, "%s[Input]: %10s, %s \n", info, if_temp->name, if_temp->long_name ? if_temp->long_name : " ");if_temp = if_temp->next;}while (of_temp != NULL) {sprintf(info, "%s[Output]: %10s, %s \n", info, of_temp->name, of_temp->long_name ? of_temp->long_name : " ");of_temp = of_temp->next;}ALOGI("%s", info);return env->NewStringUTF(info);
}JNIEXPORT jstring JNICALL
Java_com_example_nxf31081_ffmpeg_1android_1demo_12_MainActivity_avCodecInfo(JNIEnv *env, jobject instance) {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;case AVMEDIA_TYPE_SUBTITLE:sprintf(info, "%s (subtitle) : ", info);break;default:sprintf(info, "%s (other) : ", info);break;}sprintf(info, "%s[%10s] %s \n", info, c_temp->name, c_temp->long_name ? c_temp->long_name : " ");c_temp = c_temp->next;}ALOGI("%s", info);return env->NewStringUTF(info);
}JNIEXPORT jstring JNICALL
Java_com_example_nxf31081_ffmpeg_1android_1demo_12_MainActivity_avFilterInfo(JNIEnv *env, jobject instance) {char info[40000] = {0};avfilter_register_all();AVFilter *f_temp = (AVFilter *) avfilter_next(NULL);while (f_temp != NULL) {sprintf(info, "%s%s\n", info, f_temp->name);f_temp = f_temp->next;}ALOGI("%s", info);return env->NewStringUTF(info);
}}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_nxf31081_ffmpeg_1android_1demo_12_MainActivity_avConfigurationInfo(JNIEnv *env,jobject instance) {char info[10000] = {0};av_register_all();sprintf(info, "%s \n", avcodec_configuration());return env->NewStringUTF(info);
}

这时候,这个app函数就算写好了,图放在文章的开头,可以看到,我们配置的硬编解码器h264_mediacodec已经能够检测到了。在下一篇文章中再仔细分析CMakeLists.txt文件和native-lib.cpp中所使用的ffmpeg函数。

工程下载地址:https://github.com/ZER0000/ffmpeg_android_demo.git

基于Android O8.1的ffmpeg NDK 开发 - 2 - APP显示ffmpeg所支持协议,编解码,过滤器,格式,配置等信息相关推荐

  1. Android SDK+Eclipse+ADT+CDT+NDK 开发环境在windows 7下的搭建

    Android SDK+Eclipse+ADT+CDT+NDK 开发环境在windows 7下的搭建 这几天一直在研究 Android SDK C/C++平台的搭建,尽管以前有成功在Windows X ...

  2. android音乐播放器ppt,基于Android音乐播放器设计与开发.ppt

    基于Android音乐播放器设计与开发 毕业设计 基于Android的音乐播放器 设计与开发 设计概述 研究背景 研究意义 研究目标 系统演示 研究背景 随着Android智能手机的普及,用户越来越能 ...

  3. android日记本功能界面图片,基于android的日记本的设计和开发.ppt

    基于android的日记本的设计和开发 基于android的日记本的设计与开发 指导教师:闫宇帅 答辩人:廉若榕 毕业答辩 2014年5月18日 背景 手机的发展给人们的生活带来了极大的便利.以往,我 ...

  4. android项目 用手机,基于Android平台的手机记账应用开发全程实录|Android项目手机记账应用...

    <基于Android平台的手机记账应用开发全程实录> 百度云链接:http://pan.baidu.com/s/1dFFPWpr 密码: j435 01.项目概述与项目需求 02.数据库设 ...

  5. 基于Android的小巫新闻客户端开发--UI设计(主界面)

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 基于An ...

  6. 开篇--基于Android的小巫新闻客户端开发

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 开篇-- ...

  7. 基于Android平台的手机记账应用开发全程实录|Android项目手机记账应用

    <基于Android平台的手机记账应用开发全程实录> 百度云链接:http://pan.baidu.com/s/1dFFPWpr 密码: j435 01.项目概述与项目需求 02.数据库设 ...

  8. 基于Android的儿童绘本阅读与收听APP的设计与实现【附项目源码+论文说明】

    基于Android的儿童绘本阅读与收听APP的设计与实现演示 摘要 随着人们生活水平的不断提高,儿童学前教育日益受到重视.绘本作为一种历史古老.效果优秀的早教手段,利用图画和简短的文字构筑出一个跌宕起 ...

  9. WebRTC android 端支持H264编解码

    一.WebRTC源码中默认使用的H264编解码的库 1.WebRTC源码的video_coding模块中,包含了H264编解码相关的类 打开画红线的两个头文件,分别可以看到解码类中导入了ffmpeg的 ...

最新文章

  1. I.MX6 I2C DS1337 disable square-wave output
  2. 矩阵的LU分解 c++
  3. 部署Small Business Server 2003服务器之一
  4. 【ambari】Ambari Rest api 使用
  5. 解决Vmware虚拟机中没有网络连接Ubuntu无法上网
  6. Spyder设置字体
  7. 作业6 陪集 拉格朗日定理
  8. 云服务器出现502错误的原因与解决方案
  9. 007 定位明文封包call
  10. MATLAB学习笔记(二)——使用GUIDE构建App
  11. c语言用十年算入门,初识C语言_十年饮冰 难凉热血的技术博客_51CTO博客
  12. MakeMKV for mac(MKV视频格式转换工具)
  13. C# 发送邮件之QQ邮箱
  14. 物联网体系的系统构架和用途
  15. RabbitMQ-全面详解(学习总结---从入门到深化)
  16. Android 图片压缩、内存计算
  17. MIMIC IV数据库衍生表格配置
  18. 一个或多个数据库无法访问,因而不会在数据库访问选项卡中显示
  19. 【HTML期末作业】大学生抗疫感动专题网页设计作业 抗疫最美逆行者网页 致敬疫情感动人物网页设计制作
  20. 菜刀工具连接不上_win7连接打印机提示错误0x00000002的解决教程

热门文章

  1. SpringCloud Gateway + Spring Security
  2. Cisco 7600系列Supervisor Engine 720-3BXL
  3. LeGO-LOAM:Ubuntu20.04下的编译与运行
  4. 阿里云认证资格考试,yyds!
  5. 父母英语不好,孩子照样行:在家四步轻松搞定英语启蒙 读后感
  6. android app 安装
  7. 给图像增加一种噪声,构造并利用至少两种低通或高通滤波器实现频率域的滤波,并且显示滤波后的图像
  8. nedc和epa续航里程什么意思_NEDC、WLTP、EPA续航哪个才最靠谱?
  9. css打造超能陆战队--大白
  10. OpenRisc-OptiMSoC