Media3 ExoPlayer扩展FFmpeg音视频解码

1.下载Exoplayer源码
sh 复制代码
git clone https://github.com/androidx/media

参考 官方教程media/libraries/decoder_ffmpeg路径下的README.md

找到ffmpeg编译脚本:media/libraries/decoder_ffmpeg/src/main/jni路径下的build_ffmpeg.sh

sh 复制代码
//build_ffmpeg.sh
FFMPEG_MODULE_PATH="$1"
echo "FFMPEG_MODULE_PATH is ${FFMPEG_MODULE_PATH}"
NDK_PATH="$2"
echo "NDK path is ${NDK_PATH}"
HOST_PLATFORM="$3"
echo "Host platform is ${HOST_PLATFORM}"
ANDROID_ABI="$4"
echo "ANDROID_ABI is ${ANDROID_ABI}"
ENABLED_DECODERS=("${@:5}")
echo "Enabled decoders are ${ENABLED_DECODERS[@]}"
2.环境配置

按照要求分别配置:FFMPEG_MODULE_PATH NDK_PATH HOST_PLATFORM ANDROID_ABI ENABLED_DECODERS

附官网NDK下载地址:developer.android.google.cn/ndk/downloa...

音频采样格式与相应 FFmpeg 解码器名称之间的映射:

developer.android.google.cn/media/media...

sh 复制代码
#1.FFMPEG_MODULE_PATH:ExoPlayer中FFmpeg模块路径
cd media
FFMPEG_MODULE_PATH="$(pwd)/libraries/decoder_ffmpeg/src/main"
#2.NDK_PATH:NDK路径
cd android-ndk-r22b
NDK_PATH="$(pwd)"
#3.HOST_PLATFORM:编译平台,Mac为darwin-x86_64,Linux为linux-x86_64
HOST_PLATFORM="linux-x86_64"
#4.ANDROID_ABI:最小支持Android版本(如果 ANDROID_ABI 小于 21,则可以使用 NDK r23c)
ANDROID_ABI=21
#5.ENABLED_DECODERS:解码器格式
ENABLED_DECODERS=(aac ac3 mp3 flac h264 hevc)
3.下载FFmpeg及编译
sh 复制代码
git clone git://source.ffmpeg.org/ffmpeg
cd ffmpeg
#切到当前推荐的FFmpeg版本6.0
git checkout release/6.0
FFMPEG_PATH="$(pwd)"
#关联FFmpeg源码
cd "${FFMPEG_MODULE_PATH}/jni"
ln -s "$FFMPEG_PATH" ffmpeg
#编译FFmpeg
./build_ffmpeg.sh \
  "${FFMPEG_MODULE_PATH}" "${NDK_PATH}" "${HOST_PLATFORM}" "${ANDROID_ABI}" "${ENABLED_DECODERS[@]}"

编译成功会在ffmpeg生成android-libs目录,里面包含.a文件

4.下载libyuv及编译

libyuv编译脚本build_yuv.sh

sh 复制代码
#!/bin/bash
set -eu

FFMPEG_MODULE_PATH="$1"
echo "FFMPEG_MODULE_PATH is ${FFMPEG_MODULE_PATH}"
NDK_PATH="$2"
echo "NDK path is ${NDK_PATH}"
ANDROID_ABI="$3"
echo "ANDROID_ABI is ${ANDROID_ABI}"

ABI_LIST="armeabi-v7a arm64-v8a x86 x86_64"
echo "ABI List is ${ABI_LIST}"

ANDROID_ABI_64BIT="$ANDROID_ABI"
if [[ "$ANDROID_ABI_64BIT" -lt 21 ]]
then
    echo "Using ANDROID_ABI 21 for 64-bit architectures"
    ANDROID_ABI_64BIT=21
fi

cd "${FFMPEG_MODULE_PATH}/jni/libyuv"

for abi in ${ABI_LIST}; do
  rm -rf "build-${abi}"
  mkdir "build-${abi}"
  cd "build-${abi}"

  cmake .. \
    -G "Unix Makefiles" \
    -DCMAKE_TOOLCHAIN_FILE=$NDK_PATH/build/cmake/android.toolchain.cmake -DANDROID_ABI=${abi} -DCMAKE_ANDROID_ARCH_ABI=${abi} \
    -DANDROID_NDK=${NDK_PATH} \
    -DANDROID_PLATFORM=${ANDROID_ABI} \
    -DCMAKE_BUILD_TYPE=Release \
    -DBUILD_SHARED_LIBS=ON \
    -DCMAKE_SYSTEM_NAME=Generic \
    -DCMAKE_ANDROID_STL_TYPE=c++_shared \
    -DCMAKE_SYSTEM_NAME=Android \
    -DCMAKE_THREAD_PREFER_PTHREAD=TRUE \
    -DTHREADS_PREFER_PTHREAD_FLAG=TRUE \
    -DBUILD_STATIC_LIBS=OFF

  cmake --build .
  cd ..
done

for abi in ${ABI_LIST}; do
  mkdir -p "./android-libs/${abi}"
  cp -r "build-${abi}/libyuv.so" "./android-libs/${abi}/libyuv.so"
  echo "build-${abi}/libyuv.so was successfully copied to ./android-libs/${abi}/libyuv.so!"
done
sh 复制代码
#git clone https://chromium.googlesource.com/libyuv/libyuv
git clone https://gitee.com/bestchangge/libyuv
YUV_PATH="$(pwd)"
cd "${FFMPEG_MODULE_PATH}/jni"
ln -s "$YUV_PATH" libyuv
# cmake需要装一下
sudo apt update
sudo apt install cmake
# 编译libyuv
./build_yuv.sh \
  "${FFMPEG_MODULE_PATH}" "${NDK_PATH}" "${ANDROID_ABI}"

编译成功会在libyuv生成android-libs目录,里面包含.so文件

5.验证
Java 复制代码
/**
 * 创建FFmpeg渲染器工厂
 */
@UnstableApi public class FFmpegRenderersFactory extends DefaultRenderersFactory {

    public FFmpegRenderersFactory(Context context) {
        super(context);
        /**
         * EXTENSION_RENDERER_MODE_OFF:禁用扩展渲染器
         * EXTENSION_RENDERER_MODE_ON:启用扩展渲染器,但核心渲染器优先级更高
         * EXTENSION_RENDERER_MODE_PREFER:启用扩展渲染器,且扩展渲染器优先级更高
         */
        //用EXTENSION_RENDERER_MODE_PREFER测试ffmpeg,建议使用EXTENSION_RENDERER_MODE_ON
        setExtensionRendererMode(EXTENSION_RENDERER_MODE_PREFER);
    }

    @Override
    protected void buildAudioRenderers(Context context, @ExtensionRendererMode int extensionRendererMode, MediaCodecSelector mediaCodecSelector, boolean enableDecoderFallback, AudioSink audioSink, Handler eventHandler, AudioRendererEventListener eventListener, ArrayList<Renderer> out) {
        out.add(new FfmpegAudioRenderer(eventHandler, eventListener, audioSink));
        super.buildAudioRenderers(context, extensionRendererMode, mediaCodecSelector, enableDecoderFallback, audioSink, eventHandler, eventListener, out);
    }

    @Override
    protected void buildVideoRenderers(Context context, @ExtensionRendererMode int extensionRendererMode, MediaCodecSelector mediaCodecSelector, boolean enableDecoderFallback, Handler eventHandler, VideoRendererEventListener eventListener, long allowedVideoJoiningTimeMs, ArrayList<Renderer> out) {
        out.add(new FfmpegVideoRenderer(allowedVideoJoiningTimeMs,eventHandler, eventListener,MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY));
        super.buildVideoRenderers(context, extensionRendererMode, mediaCodecSelector, enableDecoderFallback, eventHandler, eventListener, allowedVideoJoiningTimeMs, out);
    }
}

创建FFmpeg渲染器工厂设置到ExoPlayer

Java 复制代码
FFmpegRenderersFactory renderersFactory = new FFmpegRenderersFactory(this);
player = new ExoPlayer.Builder(this,renderersFactory).build();

运行可以在Log控制台上看到

sh 复制代码
//视频解码
videoDecoderInitialized [eventTime=0.66, mediaPos=0.00, window=0, period=0, ffmpegLavc60.3.100-h264]
//音频解码
audioDecoderInitialized [eventTime=0.68, mediaPos=0.00, window=0, period=0, ffmpegLavc60.3.100-aac]
相关推荐
木易 士心1 天前
MVC、MVP 与 MVVM:Android 架构演进之路
android·架构·mvc
百锦再1 天前
国产数据库的平替亮点——关系型数据库架构适配
android·java·前端·数据库·sql·算法·数据库架构
走在路上的菜鸟1 天前
Android学Dart学习笔记第十三节 注解
android·笔记·学习·flutter
介一安全1 天前
【Frida Android】实战篇15:Frida检测与绕过——基于/proc/self/maps的攻防实战
android·网络安全·逆向·安全性测试·frida
hhy_smile1 天前
Android 与 java 设计笔记
android·java·笔记
laocooon5238578861 天前
C#二次开发中简单块的定义与应用
android·数据库·c#
似霰1 天前
传统 Hal 开发笔记5 —— 添加硬件访问服务
android·framework·hal
恋猫de小郭1 天前
Android 宣布 Runtime 编译速度史诗级提升:在编译时间上优化了 18%
android·前端·flutter
csj501 天前
安卓基础之《(4)—Activity组件》
android
游戏开发爱好者81 天前
H5 混合应用加密 Web 资源暴露到 IPA 层防护的完整技术方案
android·前端·ios·小程序·uni-app·iphone·webview