标签:path clu figure source workspace 播放 框架 为什么 img
该原创文章首发于微信公众号:字节流动
FFmpeg 是一款知名的开源音视频处理软件,它提供了丰富而友好的接口支持开发者进行二次开发。
FFmpeg 读作 “ef ef em peg” ,其中的 “FF” 指的是 “Fast Forward”,“mpeg” 则是 “Moving Picture Experts Group” (动态图像专家组)。
FFmpeg 项目功能复杂而庞大,基本上支持所有常见的音视频处理操作,如封装格式转换、音视频转码、音视频播放和剪辑、视频添加水印滤镜等。
尽管 FFmpeg 功能强大,但是由于其采用的是带有传染性的 LGPL/GPL 开源协议,所以一些大厂基本上都是自己独立开发类似的音视频处理库,甚至在接口和组织模块上模仿 FFmpeg 。
因此,学习 FFmpeg 不仅能够帮助你掌握音视频开发的相关知识脉络,还能让你快速适应不同的音视频处理框架。
FFmpeg 有六个常用的功能模块:
本文主要是帮助初学者快速上手 FFmpeg 的编译和集成,对 FFmpeg 项目的编译配置细节就不过多阐述,这不是本篇内容所能容纳。
这里主要选择编译 ffmpeg v4.2.2 版本,因为这个版本网上的解决方案比较多,而且大部分可行。
编译环境:
编译前准备:
//1. 下载 ffmpeg-4.2.2
wget https://ffmpeg.org/releases/ffmpeg-4.2.2.tar.bz2
//2. 解压 FFmpeg
tar -jxvf ffmpeg-4.2.2.tar.bz2
//3. 配置项目
./configure --disable-x86asm
在 FFmpeg 4.2.2 解压目录下创建编译脚本 build_android_arm64-v8a_clang.sh
:
#!/bin/bash
export NDK=/root/workspace/android-ndk-r20b #这里配置先你的 NDK 路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
function build_android
{
./configure --prefix=$PREFIX --enable-neon --enable-hwaccels --enable-gpl --disable-postproc --disable-debug --enable-small --enable-jni --enable-mediacodec --enable-decoder=h264_mediacodec --enable-static --enable-shared --disable-doc --enable-ffmpeg --disable-ffplay --disable-ffprobe --disable-avdevice --disable-doc --disable-symver --cross-prefix=$CROSS_PREFIX --target-os=android --arch=$ARCH --cpu=$CPU --cc=$CC --cxx=$CXX --enable-cross-compile --sysroot=$SYSROOT --extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" --extra-ldflags="$ADDI_LDFLAGS"
make clean
make -j16
make install
echo "============================ build android arm64-v8a success =========================="
}
#arm64-v8a
ARCH=arm64
CPU=armv8-a
API=21
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU"
build_android
编译 FFmpeg Android 平台的 64 位动态库和静态库:
# 修改 build_android_arm64-v8a_clang.sh 可执行权限
chmod +x build_android_arm64-v8a_clang.sh
# 运行编译脚本
./build_android_arm64-v8a_clang.sh
编译成功后会在 android 目录下生成对应六个模块的静态库和动态库。
另外,若要编译成 32 位的库,则需修改对应的编译脚本:
#armv7-a
ARCH=arm
CPU=armv7-a
API=21
CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
基于上节编译好的 FFmpeg 静态库,我们在 Android Studio 上进行简单的集成测试。
我们可以按照上图所示,将 FFmpeg 各个模块的静态库和头文件放置到指定目录下,实现一个获取各个模块版本信息的 jni 。
```c++
#include <cstdio>
#include <cstring>
#include "util/LogUtil.h"
#include "jni.h"
//由于 FFmpeg 库是 C 语言实现的,告诉编译器按照 C 的规则进行编译
extern "C" {
#include <libavcodec/version.h>
#include <libavcodec/avcodec.h>
#include <libavformat/version.h>
#include <libavutil/version.h>
#include <libavfilter/version.h>
#include <libswresample/version.h>
#include <libswscale/version.h>
};
#ifdef __cplusplus
extern "C" {
#endif
/*
#ifdef __cplusplus
}
#endif
Java 层的调用逻辑:
```java
package com.byteflow.learnffmpeg.media;
public class FFMediaPlayer {
static {
System.loadLibrary("learn-ffmpeg");
}
public static String GetFFmpegVersion() {
return native_GetFFmpegVersion();
}
private static native String native_GetFFmpegVersion();
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((TextView)findViewById(R.id.text_view)).setText(FFMediaPlayer.GetFFmpegVersion());
}
}
CMakeLists.txt 构建脚本:
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
set(jnilibs ${CMAKE_SOURCE_DIR}/../jniLibs)
set(libname learn-ffmpeg)
include_directories(
include
${CMAKE_SOURCE_DIR}/util
)
link_directories(
${jnilibs}/${ANDROID_ABI})
file(GLOB src-files
${CMAKE_SOURCE_DIR}/*.cpp)
add_library( # Sets the name of the library.
${libname}
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
${src-files}
)
set(third-party-libs
avformat
avcodec
avfilter
swresample
swscale
avutil
)
set(native-libs
android
EGL
GLESv3
OpenSLES
log
m
z
)
target_link_libraries( # Specifies the target library.
${libname}
# Links the target library to the log library
# included in the NDK.
${log-lib}
${third-party-libs}
${native-libs}
)
编译完成后,运行 App 获取 FFmpeg 各个模块版本和编译配置信息。
https://blog.csdn.net/leixiaohua1020
https://juejin.im/post/5e1eace16fb9a02fec66474e
有疑问或技术交流可以添加我的微信:Byte-Flow
标签:path clu figure source workspace 播放 框架 为什么 img
原文地址:https://blog.51cto.com/11216530/2532157