基于 FFmpeg 的跨平台视频播放器简明教程(十):在 Android 运行 FFmpeg
系列文章目录
- 基于 FFmpeg 的跨平台视频播放器简明教程(一):FFMPEG + Conan 环境集成
- 基于 FFmpeg 的跨平台视频播放器简明教程(二):基础知识和解封装(demux)
- 基于 FFmpeg 的跨平台视频播放器简明教程(三):视频解码
- 基于 FFmpeg 的跨平台视频播放器简明教程(四):像素格式与格式转换
- 基于 FFmpeg 的跨平台视频播放器简明教程(五):使用 SDL 播放视频
- 基于 FFmpeg 的跨平台视频播放器简明教程(六):使用 SDL 播放音频和视频
- 基于 FFmpeg 的跨平台视频播放器简明教程(七):使用多线程解码视频和音频
- 基于 FFmpeg 的跨平台视频播放器简明教程(八):音画同步
- 基于 FFmpeg 的跨平台视频播放器简明教程(九):Seek 策略
前言
在前九章的学习中,我们已经成功地实现了一个基础的播放器,它拥有视频播放、音画同步、快进/快退等基本功能。当然,这个简易的示例还有许多可以优化的地方,比如添加更美观的用户界面,或者增加字幕功能等。然而,这并不是本教程的主要关注点。本系列文章更关注于跨平台播放器框架的构建,特别是在移动端。因此,从本章开始,我们将把重点转向 Android 端播放器的开发。
前置知识包括一些 Android 的基本开发,以及 JNI 开发等。这些前置知识默认你有所了解,本文不会涉及。关于 JNI 可以参考笔者之前写的 JNI 简明教程之手把手教你入门
本文代码在 android/tutorial01。
FFmpeg Android 编译
FFmpeg 的跨端编译也是老生常谈的话题了,本文不去讨论那些细节问题,只想提供一种最便捷的编译方法。在 CompilationGuide/Android 中给出了一些指导意见,例如直接使用已经编译好的 so,或者使用别人写好的脚本。对比了这几个方法,ffmpeg-android-maker 比较合适,优势包括:
- 网上那些已经编译好的 ffmpeg so,ffmepg 版本可能太老了。ffmpeg-android-maker 则是从源码直接编译
- ffmpeg-android-maker 能够自动拉取 ffmpeg 源码,只需要设置少量的变量就能开始编译
- ffmpeg-android-maker 功能、文档写的比较清楚,用起来没有卡点。
那么基于 ffmpeg-android-maker 要如何编译 android ffmpeg 呢?非常简单,步骤如下。
- 下载 ffmpeg-android-marker 仓库
git clone git@github.com:Javernaut/ffmpeg-android-maker.git
cd ffmpeg-android-maker
- 设置环境变量
export ANDROID_SDK_HOME=/Users/user/Library/Android/sdk
export ANDROID_NDK_HOME=/Users/user/Library/Android/sdk/ndk/25.2.9519653
- 运行脚本
./ffmpeg-android-maker.sh
编译成功后,你可以在当前文件夹的 build 目录下找到各个架构的 ffmpeg 库:
build
└── ffmpeg├── arm64-v8a│ ├── bin│ ├── include│ ├── lib│ └── share├── armeabi-v7a│ ├── bin│ ├── include│ ├── lib│ └── share├── x86│ ├── bin│ ├── include│ ├── lib│ └── share└── x86_64├── bin├── include├── lib└── share
其中 include 和 lib 是我们需要的。
FFmpeg so 导入 Android 项目
将 so 文件放置在正确的位置
第一步当然是将编译好的 ffmpeg so 文件和头文件拷贝到我们的项目中。在编译产物中,我们只需要 include 和 lib 文件夹即可,将它们拷贝至 3rdparty/ffmpeg/android 目录下。当然你也可以选择其他地方,这只是我个人的选择。
android
├── arm64-v8a
│ ├── include
│ └── lib
├── armeabi-v7a
│ ├── include
│ └── lib
├── x86
│ ├── include
│ └── lib
└── x86_64├── include└── lib
写 CMake 将 FFmpeg so 引入项目
ffmpeg 有多个 so 文件,在编译项目的过程中,如果一个一个地去写 link 命令有点麻烦。通常的做法是,创建一个新的 library,例如叫 ffmpeg_libs,让 ffmpeg_libs 去 link 这些 so 文件,然后其他模块 link ffmpeg_libs 就能够链式地将所有依赖都带上了。
这部分属于 CMake 的知识范畴,不细说了,可以参考笔者之前写的 现代 CMake 简明教程(一)- CMake 基础。具体 CMake 源码在 CMakeLists.txt 大家自己看。
写 Kotlin 和 JNI 调用 FFmpeg API
Android app 想要调用 C/C++ 的接口就必须通过 JNI 接口来实现。首先,在应用层定义一个 native method 叫 stringFromFFMPEG
external fun stringFromFFMPEG(): String
接着定义 JNI 层接口,新建 src/cpp/native-lib.cpp 文件,并完成 JNI 层代码:
#include <jni.h>
#include <string>
extern "C"
{
#include <libavutil/avutil.h>
}extern "C" JNIEXPORT jstring JNICALL
Java_com_test_tutorial01_MainActivity_stringFromFFMPEG(JNIEnv* env,jobject /* this */) {std::string hello = "Hello from ffmpeg: " + std::string(av_version_info());return env->NewStringUTF(hello.c_str());
}
最后,我们将 UI 上的 TextView 中的字符串内容修改为这个函数的返回值即可:
binding.sampleText.text = stringFromFFMPEG()
最终呈现的效果如下图:

总结
本文介绍了一种非常便捷的编译 android ffmpeg 的方法:ffmpeg-android-maker。说明如何将 ffmpeg so 库导入至 android 项目中,并提供了实例代码(代码地址:这里)
参考
- JNI 简明教程之手把手教你入门
- CompilationGuide/Android
- 现代 CMake 简明教程(一)- CMake 基础
相关文章:
基于 FFmpeg 的跨平台视频播放器简明教程(十):在 Android 运行 FFmpeg
系列文章目录 基于 FFmpeg 的跨平台视频播放器简明教程(一):FFMPEG Conan 环境集成基于 FFmpeg 的跨平台视频播放器简明教程(二):基础知识和解封装(demux)基于 FFmpeg 的跨平台视频…...
正点原子嵌入式linux驱动开发——Linux LCD驱动
LCD是很常用的一个外设,通过LCD可以显示绚丽的图片、界面等,提交人机交互的效率。STM32MP1提供了一个LTDC接口用于连接RGB接口的液晶屏。本章就来学校一下如何在Linux下驱动LCD屏。 LCD和LTDC简介 LCD简介 这里在当时学习stm32裸机开发的时候就学过了…...
2-Java进阶知识总结-6-多线程
文章目录 多线程--基本概念并发和并行进程和线程多线程 多线程--实现方式一,继承Thread类方法介绍实现步骤注意事项 方式二,实现Runnable接口Thread构造方法实现步骤 方式三,实现Callable接口方法介绍实现步骤 三种多线程实现方法对比 多线程…...
openwrt下游设备在校园网(DLUT-LingShui)中使用ipv6网络
背景:校园网最多支持6台设备的无感认证,需要使用路由器(本人使用openwrt系统)为更多的设备提供网络,但校园网分配的ipv6地址子网为/128,不能为路由器下的设备分配全球ipv6地址,因此需要使用nat6转发下游设备的局域网ip…...
10个基于.Net开发的Windows开源软件项目
1、基于.NET的强大软件开发工具 一个基于.Net Core构建的简单、跨平台快速开发框架。JNPF开发平台前后端封装了上千个常用类,方便扩展;集成了代码生成器,支持前后端业务代码生成,满足快速开发,提升工作效率;…...
Java多线程秘籍,掌握这5种方法,让你的代码优化升级
介绍5种多线程方法,助您提高编码效率! 如果您的应用程序与那些能够同时处理多个任务的应用程序相比表现不佳,很可能是因为它是单线程的。解决这个问题的方法之一是采用多线程技术。 以下是一些可以考虑的方法: 线程(…...
npm install报错 缺少python
报错信息: Building:E:tolsnvmnodesnodeexe : ode emos ant-desig-we-eos odemodules node-gypbintnode-gp.s rebld -verbose -Libsass_ext --Libsas_cflags- lags --libsass_librarygyp info it worked if it ends with ok gyp verb cli [ gyp verb cliE: toolsnv…...
达梦:开启sql日志记录
前言 开启sql日志记录,可协助排查定位数据库问题。生产开启会有一定的性能消耗,建议打开 SQL 日志异步刷盘功能 1.配置sqllog.ini文件 sqllog.ini 用于 SQL 日志的配置,当且仅当 INI 参数 SVR_LOG1 时使用。 运行中的数据库实例,可…...
C语言开发,指针进阶,字符串查找,包含,拼接
文章目录 C语言开发,指针进阶。1.字符串与指针的关系2.指针获取字符串具体内容3.字符串比较,查找,包含,拼接4.字符串大小写 C语言开发,指针进阶。 1.字符串与指针的关系 // // Created by MagicBook on 2023-10-22. …...
PyCharm中文使用详解
PyCharm是一个Python IDE,可以帮助程序员节省时间,提高生产力。那么具体怎么用呢?本文介绍了PyCharm的安装、插件、外部工具、专业功能等,希望对大家有所帮助。 之前没有系统介绍过PyCharm。如何配置环境,如何DeBug&a…...
一键同步,无处不在的书签体验:探索多电脑Chrome书签同步插件
说在前面 平时大家都是怎么管理自己的浏览器书签数据的呢?有没有过公司和家里的电脑浏览器书签不同步的情况?有没有过电脑突然坏了但书签数据没有导出,导致书签数据丢失了?解决这些问题的方法有很多,我选择自己写个chr…...
在Go项目中二次封装Kafka客户端功能
1.摘要 在上一章节中,我利用Docker快速搭建了一个Kafka服务,并测试成功Kafka生产者和消费者功能,本章内容尝试在Go项目中对Kafka服务进行封装调用, 实现从Kafka自动接收消息并消费。 在本文中使用了Kafka的一个高性能开源库Sarama, Sarama是一个遵循MIT许可协议的Apache Kafk…...
CVE-2021-44228 Apache log4j 远程命令执行漏洞
一、漏洞原理 log4j(log for java)是由Java编写的可靠、灵活的日志框架,是Apache旗下的一个开源项目,使用Log4j,我们更加方便的记录了日志信息,它不但能控制日志输出的目的地,也能控制日志输出的内容格式;…...
前端跨域相关
注:前端配置跨域后服务器端(Nginx)也需要配置,否则接口无法访问 vue跨域 配置文件 /vue.config.js devServer: { port: 7100, proxy: { /api: { target: http://域名, changeOrigin: true, logLevel: debug, pathRewrite: { ^/…...
HTML笔记-狂神
1. 初识HTML 什么是HTML? Hyper Text Markup Language : 超文本标记语言 超文本包括:文字、图片、音频、视频、动画等 目前使用的是HTML5,使用 W3C标准 W3C标准包括: 结构化标准语言(HTML、XML) 表现标…...
python自动化测试工具selenium
概述 selenium是网页应用中最流行的自动化测试工具,可以用来做自动化测试或者浏览器爬虫等。官网地址为:Selenium。相对于另外一款web自动化测试工具QTP来说有如下优点: 免费开源轻量级,不同语言只需要一个体积很小的依赖包支持…...
输入/输出应用程序接口和设备驱动程序接口
文章目录 1.输入/输出应用程序接口1.字符设备接口2.块设备接口3.网络设备接口1.网络设备套接字通信 4.阻塞/非阻塞I/O 2.设备驱动程序接口1.统一标准的设备驱动程序接口 1.输入/输出应用程序接口 1.字符设备接口 get/put系统调用:向字符设备读/写一个字符 2.块设备接口 read/wr…...
Python---Socket 网络通信
Socket :进程之间通信的工具,进程之间想要进行网络通信需要Socket,两个进程之间通过socket进行相互通讯,就必须有服务端和客服端。 Socket服务端编程 # 1.创建socket对象 import socketsocket_server socket.socket()# 2. 绑定socket_server到指定IP和…...
使用 jdbc 技术升级水果库存系统(优化版本)
抽取执行更新方法抽取查询方法 —— ResultSetMetaData ResultSetMetaData rsmd rs.getMetaData();//元数据,结果集的结构数据 抽取查询方法 —— 解析结果集封装成实体对象提取 获取连接 和 释放资源 的方法将数据库配置信息转移到配置文件 <dependencies><depend…...
网络协议--广播和多播
12.1 引言 在第1章中我们提到有三种IP地址:单播地址、广播地址和多播地址。本章将更详细地介绍广播和多播。 广播和多播仅应用于UDP,它们对需将报文同时传往多个接收者的应用来说十分重要。TCP是一个面向连接的协议,它意味着分别运行于两主…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
k8s从入门到放弃之HPA控制器
k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率(或其他自定义指标)来调整这些对象的规模,从而帮助应用程序在负…...
es6+和css3新增的特性有哪些
一:ECMAScript 新特性(ES6) ES6 (2015) - 革命性更新 1,记住的方法,从一个方法里面用到了哪些技术 1,let /const块级作用域声明2,**默认参数**:函数参数可以设置默认值。3&#x…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...
