当前位置: 首页 > news >正文

基于 FFmpeg 的跨平台视频播放器简明教程(十):在 Android 运行 FFmpeg

系列文章目录

  1. 基于 FFmpeg 的跨平台视频播放器简明教程(一):FFMPEG + Conan 环境集成
  2. 基于 FFmpeg 的跨平台视频播放器简明教程(二):基础知识和解封装(demux)
  3. 基于 FFmpeg 的跨平台视频播放器简明教程(三):视频解码
  4. 基于 FFmpeg 的跨平台视频播放器简明教程(四):像素格式与格式转换
  5. 基于 FFmpeg 的跨平台视频播放器简明教程(五):使用 SDL 播放视频
  6. 基于 FFmpeg 的跨平台视频播放器简明教程(六):使用 SDL 播放音频和视频
  7. 基于 FFmpeg 的跨平台视频播放器简明教程(七):使用多线程解码视频和音频
  8. 基于 FFmpeg 的跨平台视频播放器简明教程(八):音画同步
  9. 基于 FFmpeg 的跨平台视频播放器简明教程(九):Seek 策略

前言

在前九章的学习中,我们已经成功地实现了一个基础的播放器,它拥有视频播放、音画同步、快进/快退等基本功能。当然,这个简易的示例还有许多可以优化的地方,比如添加更美观的用户界面,或者增加字幕功能等。然而,这并不是本教程的主要关注点。本系列文章更关注于跨平台播放器框架的构建,特别是在移动端。因此,从本章开始,我们将把重点转向 Android 端播放器的开发。

前置知识包括一些 Android 的基本开发,以及 JNI 开发等。这些前置知识默认你有所了解,本文不会涉及。关于 JNI 可以参考笔者之前写的 JNI 简明教程之手把手教你入门

本文代码在 android/tutorial01。

FFmpeg Android 编译

FFmpeg 的跨端编译也是老生常谈的话题了,本文不去讨论那些细节问题,只想提供一种最便捷的编译方法。在 CompilationGuide/Android 中给出了一些指导意见,例如直接使用已经编译好的 so,或者使用别人写好的脚本。对比了这几个方法,ffmpeg-android-maker 比较合适,优势包括:

  1. 网上那些已经编译好的 ffmpeg so,ffmepg 版本可能太老了。ffmpeg-android-maker 则是从源码直接编译
  2. ffmpeg-android-maker 能够自动拉取 ffmpeg 源码,只需要设置少量的变量就能开始编译
  3. ffmpeg-android-maker 功能、文档写的比较清楚,用起来没有卡点。

那么基于 ffmpeg-android-maker 要如何编译 android ffmpeg 呢?非常简单,步骤如下。

  1. 下载 ffmpeg-android-marker 仓库
git clone git@github.com:Javernaut/ffmpeg-android-maker.git
cd ffmpeg-android-maker
  1. 设置环境变量
export ANDROID_SDK_HOME=/Users/user/Library/Android/sdk
export ANDROID_NDK_HOME=/Users/user/Library/Android/sdk/ndk/25.2.9519653
  1. 运行脚本
./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 的跨平台视频播放器简明教程&#xff08;一&#xff09;&#xff1a;FFMPEG Conan 环境集成基于 FFmpeg 的跨平台视频播放器简明教程&#xff08;二&#xff09;&#xff1a;基础知识和解封装&#xff08;demux&#xff09;基于 FFmpeg 的跨平台视频…...

正点原子嵌入式linux驱动开发——Linux LCD驱动

LCD是很常用的一个外设&#xff0c;通过LCD可以显示绚丽的图片、界面等&#xff0c;提交人机交互的效率。STM32MP1提供了一个LTDC接口用于连接RGB接口的液晶屏。本章就来学校一下如何在Linux下驱动LCD屏。 LCD和LTDC简介 LCD简介 这里在当时学习stm32裸机开发的时候就学过了…...

2-Java进阶知识总结-6-多线程

文章目录 多线程--基本概念并发和并行进程和线程多线程 多线程--实现方式一&#xff0c;继承Thread类方法介绍实现步骤注意事项 方式二&#xff0c;实现Runnable接口Thread构造方法实现步骤 方式三&#xff0c;实现Callable接口方法介绍实现步骤 三种多线程实现方法对比 多线程…...

openwrt下游设备在校园网(DLUT-LingShui)中使用ipv6网络

背景&#xff1a;校园网最多支持6台设备的无感认证&#xff0c;需要使用路由器(本人使用openwrt系统)为更多的设备提供网络&#xff0c;但校园网分配的ipv6地址子网为/128&#xff0c;不能为路由器下的设备分配全球ipv6地址&#xff0c;因此需要使用nat6转发下游设备的局域网ip…...

10个基于.Net开发的Windows开源软件项目

1、基于.NET的强大软件开发工具 一个基于.Net Core构建的简单、跨平台快速开发框架。JNPF开发平台前后端封装了上千个常用类&#xff0c;方便扩展&#xff1b;集成了代码生成器&#xff0c;支持前后端业务代码生成&#xff0c;满足快速开发&#xff0c;提升工作效率&#xff1b…...

Java多线程秘籍,掌握这5种方法,让你的代码优化升级

介绍5种多线程方法&#xff0c;助您提高编码效率&#xff01; 如果您的应用程序与那些能够同时处理多个任务的应用程序相比表现不佳&#xff0c;很可能是因为它是单线程的。解决这个问题的方法之一是采用多线程技术。 以下是一些可以考虑的方法&#xff1a; 线程&#xff08;…...

npm install报错 缺少python

报错信息&#xff1a; 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日志记录&#xff0c;可协助排查定位数据库问题。生产开启会有一定的性能消耗&#xff0c;建议打开 SQL 日志异步刷盘功能 1.配置sqllog.ini文件 sqllog.ini 用于 SQL 日志的配置&#xff0c;当且仅当 INI 参数 SVR_LOG1 时使用。 运行中的数据库实例&#xff0c;可…...

C语言开发,指针进阶,字符串查找,包含,拼接

文章目录 C语言开发&#xff0c;指针进阶。1.字符串与指针的关系2.指针获取字符串具体内容3.字符串比较&#xff0c;查找&#xff0c;包含&#xff0c;拼接4.字符串大小写 C语言开发&#xff0c;指针进阶。 1.字符串与指针的关系 // // Created by MagicBook on 2023-10-22. …...

PyCharm中文使用详解

PyCharm是一个Python IDE&#xff0c;可以帮助程序员节省时间&#xff0c;提高生产力。那么具体怎么用呢&#xff1f;本文介绍了PyCharm的安装、插件、外部工具、专业功能等&#xff0c;希望对大家有所帮助。 之前没有系统介绍过PyCharm。如何配置环境&#xff0c;如何DeBug&a…...

一键同步,无处不在的书签体验:探索多电脑Chrome书签同步插件

说在前面 平时大家都是怎么管理自己的浏览器书签数据的呢&#xff1f;有没有过公司和家里的电脑浏览器书签不同步的情况&#xff1f;有没有过电脑突然坏了但书签数据没有导出&#xff0c;导致书签数据丢失了&#xff1f;解决这些问题的方法有很多&#xff0c;我选择自己写个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编写的可靠、灵活的日志框架&#xff0c;是Apache旗下的一个开源项目&#xff0c;使用Log4j&#xff0c;我们更加方便的记录了日志信息&#xff0c;它不但能控制日志输出的目的地&#xff0c;也能控制日志输出的内容格式&#xff1b;…...

前端跨域相关

注&#xff1a;前端配置跨域后服务器端&#xff08;Nginx&#xff09;也需要配置&#xff0c;否则接口无法访问 vue跨域 配置文件 /vue.config.js devServer: { port: 7100, proxy: { /api: { target: http://域名, changeOrigin: true, logLevel: debug, pathRewrite: { ^/…...

HTML笔记-狂神

1. 初识HTML 什么是HTML&#xff1f; Hyper Text Markup Language : 超文本标记语言 超文本包括&#xff1a;文字、图片、音频、视频、动画等 目前使用的是HTML5&#xff0c;使用 W3C标准 W3C标准包括&#xff1a; 结构化标准语言&#xff08;HTML、XML&#xff09; 表现标…...

python自动化测试工具selenium

概述 selenium是网页应用中最流行的自动化测试工具&#xff0c;可以用来做自动化测试或者浏览器爬虫等。官网地址为&#xff1a;Selenium。相对于另外一款web自动化测试工具QTP来说有如下优点&#xff1a; 免费开源轻量级&#xff0c;不同语言只需要一个体积很小的依赖包支持…...

输入/输出应用程序接口和设备驱动程序接口

文章目录 1.输入/输出应用程序接口1.字符设备接口2.块设备接口3.网络设备接口1.网络设备套接字通信 4.阻塞/非阻塞I/O 2.设备驱动程序接口1.统一标准的设备驱动程序接口 1.输入/输出应用程序接口 1.字符设备接口 get/put系统调用:向字符设备读/写一个字符 2.块设备接口 read/wr…...

Python---Socket 网络通信

Socket &#xff1a;进程之间通信的工具,进程之间想要进行网络通信需要Socket&#xff0c;两个进程之间通过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地址&#xff1a;单播地址、广播地址和多播地址。本章将更详细地介绍广播和多播。 广播和多播仅应用于UDP&#xff0c;它们对需将报文同时传往多个接收者的应用来说十分重要。TCP是一个面向连接的协议&#xff0c;它意味着分别运行于两主…...

python爬虫入门(三)正则表达式

开源中国提供的正则表达式测试工具 http://tool.oschina.net/regex/&#xff0c;输入待匹配的文本&#xff0c;然后选择常用的正则表达式&#xff0c;就可以得出相应的匹配结果了 常用的匹配规则如下 模  式描  述\w匹配字母、数字及下划线\W匹配不是字母、数字及下划线的…...

fabric.js介绍

fabric.js是可以简化canvas编写的js库&#xff0c;提供canvas缺少的对象模型&#xff0c;包含动画、数据序列化和反序列化的等高级功能的js库&#xff0c;开源项目&#xff0c;在GitHub有很多人贡献。 官网&#xff1a;Fabric.js Javascript Canvas Library (fabricjs.com) 文档…...

YOLOv5源码中的参数超详细解析(3)— 训练部分(train.py)| 模型训练调参

前言:Hello大家好,我是小哥谈。YOLOv5项目代码中,train.py是用于模型训练的代码,是YOLOv5中最为核心的代码之一,而代码中的训练参数则是核心中的核心,只有学会了各种训练参数的真正含义,才能使用YOLOv5进行最基本的训练。🌈 前期回顾: YOLOv5源码中的参数超详细解析…...

Linux高性能编程学习-TCP/IP协议族

一、TCP/IP协议族结构与主要协议 分层&#xff1a;数据链路层、网络层、传输层、应用层 1. 数据链路层 功能&#xff1a;实现网卡驱动程序&#xff0c;处理数据在不同物理介质的传输 协议&#xff1a; ARP&#xff1a;将目标机器的IP地址转成MAC地址RARP&#xff1a;将MAC地…...

用爬虫代码爬取高音质音频示例

目录 一、准备工作 1、安装Python和相关库 2、确定目标网站和数据结构 二、编写爬虫代码 1、导入库 2、设置代理IP 3、发送HTTP请求并解析HTML页面 4、查找音频文件链接 5、提取音频文件名和下载链接 6、下载音频文件 三、完整代码示例 四、注意事项 1、遵守法律法…...

深度学习与计算机视觉(一)

文章目录 计算机视觉与图像处理的区别人工神经元感知机 - 分类任务Sigmoid神经元/对数几率回归对数损失/交叉熵损失函数梯度下降法- 极小化对数损失函数线性神经元/线性回归均方差损失函数-线性回归常用损失函数使用梯度下降法训练线性回归模型线性分类器多分类器的决策面 soft…...

【vector题解】杨辉三角 | 删除有序数组中的重复项 | 只出现一次的数字Ⅱ

杨辉三角 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1…...

金字塔切分注意力模块PSA学习笔记 (附代码)

已有研究表明&#xff1a;将注意力模块嵌入到现有CNN中可以带来显著的性能提升。比如&#xff0c;SENet、BAM、CBAM、ECANet、GCNet、FcaNet等注意力机制均带来了可观的性能提升。但是&#xff0c;目前仍然存在两个具有挑战性的问题需要解决。一是如何有效地获取和利用不同尺度…...

Jenkins自动化测试

学习 Jenkins 自动化测试的系列文章 Robot Framework 概念Robot Framework 安装Pycharm Robot Framework 环境搭建Robot Framework 介绍Jenkins 自动化测试 1. Robot Framework 概念 Robot Framework是一个基于Python的&#xff0c;可扩展的关键字驱动的自动化测试框架。 它…...

python 字典dict和列表list的读取速度问题, range合并

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 python 字典和列表的读取速度问题 最近在进行基因组数据处理的时候&#xff0c;需要读取较大数据&#xff08;2.7G&#xff09;存入字典中&#xff0c; 然后对被处理数据进行字典key值的匹配&#xff0c;在被处理文件中每次…...