Skip to content

macOS 编译 ​

在 macOS M2 上编译使用 FFmpeg 与 JNI 的项目,您可以按照以下步骤进行配置和构建:

1. 准备工作 ​

1. 是否需要使用 vcpkg? ​

  • 不一定
    在 macOS 上,推荐使用 Homebrew 来安装 FFmpeg、lame 等依赖,因为 Homebrew 在 macOS 平台具有更高的普及率和维护性。

  • 可选方案
    如果您希望在跨平台开发中保持一致的依赖管理工具,或习惯使用 vcpkg,也可以选择使用 vcpkg。不过对于 macOS 平台来说,vcpkg 的使用并非必须。


2. macOS vcpkg 安装的 FFmpeg 是动态库吗? ​

  • 是的
    在 macOS 上,通过 vcpkg 安装的 FFmpeg 默认生成的是动态库(文件扩展名为 .dylib)。这与 Homebrew 安装的方式类似,都提供动态链接的 FFmpeg 库。

  • 注意事项

    • 如果使用 vcpkg,请确保在 CMakeLists.txt 中正确指定 vcpkg 工具链文件(例如通过 -DCMAKE_TOOLCHAIN_FILE=path/to/vcpkg/scripts/buildsystems/vcpkg.cmake)。
    • 同时也可查看 vcpkg 的配置选项,确认生成的是动态库(默认配置下 macOS 一般为动态库)。

3.环境准备 ​

  • 安装 Xcode 与命令行工具
    确保已经安装 Xcode 以及其命令行工具(Command Line Tools),这为编译 C/C++ 代码提供必备环境。

  • 安装 Homebrew(可选)
    Homebrew 是 macOS 上非常流行的包管理器,可以方便地安装各类依赖:

    bash
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  • 安装 Java 开发环境
    下载并安装 JDK(例如 AdoptOpenJDK 或 Oracle JDK),并确保配置好 JAVA_HOME 环境变量:

    bash
    export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home

    or

    export JAVA_HOME=/Users/ec2-user/java/jdk1.8.0_381.jdk/Contents/Home

1.2 安装 FFmpeg 与其他依赖 ​

macOS 上可以通过两种方式安装依赖库:

方式 A:使用 Homebrew(推荐) ​

  • 安装 FFmpeg 以及开发包:

    bash
    brew install ffmpeg

    Homebrew 安装的 FFmpeg 默认会提供动态库(.dylib)。

  • 如果项目需要 libmp3lame 等组件,也可以一起安装:

    bash
    brew install lame

方式 B:使用 vcpkg(可选) ​

  • vcpkg 也支持 macOS,但在 macOS 上并不是必须的,因为 Homebrew 更加主流且方便。
  • 如果您选择使用 vcpkg,请先按照 vcpkg 官方文档 安装和配置 vcpkg。

1.3 克隆代码 ​

bash
git clone https://github.com/litongjava/native-media.git
cd native-media

1.4 配置 CMake 构建脚本 ​

在 CMakeLists.txt 中配置项目时,需要查找 JNI、FFmpeg 等依赖。例如:

在 macOS 平台上,如果使用 Homebrew 安装 FFmpeg,那么一般不需要单独 target_link mp3lame,因为:

  • 集成情况:Homebrew 安装的 FFmpeg 通常已经编译时内置或动态链接了 mp3lame 支持,所以不需要额外链接 mp3lame 库。
  • 动态链接:FFmpeg 动态库中已经包含了对 MP3 编码器的支持(例如 libmp3lame),调用时系统会自动解析这些依赖。

因此,在 macOS 下只需正确查找并链接 FFmpeg 的相关动态库(如 avcodec、avformat、swresample、avutil)即可,无需额外 target_link mp3lame。

cmake
cmake_minimum_required(VERSION 3.15)
project(native_media)

set(CMAKE_CXX_STANDARD 17)

# Find JNI
find_package(JNI REQUIRED)
include_directories(${JNI_INCLUDE_DIRS})

# Find FFmpeg components explicitly
find_path(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h)
find_path(AVFORMAT_INCLUDE_DIR libavformat/avformat.h)
find_path(SWRESAMPLE_INCLUDE_DIR libswresample/swresample.h)
find_path(AVUTIL_INCLUDE_DIR libavutil/avutil.h)

find_library(AVCODEC_LIBRARY avcodec)
find_library(AVFORMAT_LIBRARY avformat)
find_library(SWRESAMPLE_LIBRARY swresample)
find_library(AVUTIL_LIBRARY avutil)

# Print paths for debugging
message(STATUS "AVCODEC_INCLUDE_DIR: ${AVCODEC_INCLUDE_DIR}")
message(STATUS "AVCODEC_LIBRARY: ${AVCODEC_LIBRARY}")
message(STATUS "AVFORMAT_INCLUDE_DIR: ${AVFORMAT_INCLUDE_DIR}")
message(STATUS "AVFORMAT_LIBRARY: ${AVFORMAT_LIBRARY}")
message(STATUS "SWRESAMPLE_INCLUDE_DIR: ${SWRESAMPLE_INCLUDE_DIR}")
message(STATUS "SWRESAMPLE_LIBRARY: ${SWRESAMPLE_LIBRARY}")
message(STATUS "AVUTIL_INCLUDE_DIR: ${AVUTIL_INCLUDE_DIR}")
message(STATUS "AVUTIL_LIBRARY: ${AVUTIL_LIBRARY}")

# 检测操作系统类型
if(WIN32)
    message(STATUS "Configuring for Windows")
    find_package(mp3lame CONFIG REQUIRED)
elseif(APPLE)
    message(STATUS "Configuring for macOS")
elseif(UNIX)
    message(STATUS "Configuring for Linux/UNIX")
endif()



# Include directories
include_directories(
        ${AVCODEC_INCLUDE_DIR}
        ${AVFORMAT_INCLUDE_DIR}
        ${SWRESAMPLE_INCLUDE_DIR}
        ${AVUTIL_INCLUDE_DIR}
        jni
)

# Add sources
add_library(native_media SHARED src/native_mp3.c src/native_mp4.c)

# Link libraries
target_link_libraries(native_media
        ${JNI_LIBRARIES}
        ${AVCODEC_LIBRARY}
        ${AVFORMAT_LIBRARY}
        ${SWRESAMPLE_LIBRARY}
        ${AVUTIL_LIBRARY})

if(WIN32)
    target_link_libraries(native_media mp3lame::mp3lame)
elseif(APPLE)

elseif(UNIX)
    target_link_libraries(native_media mp3lame)
endif()




# Add test executable
add_executable(mp4_test src/mp4_test.c src/native_mp4.c)
target_link_libraries(mp4_test
        ${AVCODEC_LIBRARY}
        ${AVFORMAT_LIBRARY}
        ${SWRESAMPLE_LIBRARY}
        ${AVUTIL_LIBRARY}
)

1.5 编译项目 ​

进入项目根目录后,按照以下步骤进行编译:

  1. 生成构建文件
    建议使用 Release 模式:

    bash
    cmake -S . -B cmake-build-release -DCMAKE_BUILD_TYPE=Release
-- The C compiler identification is AppleClang 15.0.0.15000309
-- The CXX compiler identification is AppleClang 15.0.0.15000309
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found JNI: /Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/include  found components: AWT JVM
-- AVCODEC_INCLUDE_DIR: /opt/homebrew/include
-- AVCODEC_LIBRARY: /opt/homebrew/lib/libavcodec.dylib
-- AVFORMAT_INCLUDE_DIR: /opt/homebrew/include
-- AVFORMAT_LIBRARY: /opt/homebrew/lib/libavformat.dylib
-- SWRESAMPLE_INCLUDE_DIR: /opt/homebrew/include
-- SWRESAMPLE_LIBRARY: /opt/homebrew/lib/libswresample.dylib
-- AVUTIL_INCLUDE_DIR: /opt/homebrew/include
-- AVUTIL_LIBRARY: /opt/homebrew/lib/libavutil.dylib
-- Configuring for Linux/UNIX
-- Configuring done (1.8s)
-- Generating done (0.0s)
-- Build files have been written to: /Users/ping/code/cpp/native-media/cmake-build-release
  1. 编译项目
    在构建目录下运行:

    bash
    cmake --build cmake-build-release  --target all
  2. 生成的共享库
    编译完成后,将生成类似 libnative_media.dylib 的共享库,可在 Java 中通过 System.loadLibrary("native_media") 加载。


总结 ​

  • 编译步骤:在 macOS M2 上,您可以使用 Xcode/命令行工具和 CMake 构建项目;依赖安装方面,推荐使用 Homebrew,但 vcpkg 也是可选方案。
  • 是否使用 vcpkg:在 macOS 上不强制要求使用 vcpkg,因为 Homebrew 提供了更友好的安装体验。
  • FFmpeg 库类型:无论是通过 Homebrew 还是 vcpkg 安装,默认情况下 FFmpeg 提供的是动态库(.dylib)。

通过以上步骤,您可以在 macOS M2 上顺利编译和运行基于 JNI 调用 FFmpeg 的项目。如果有其他问题或需要更详细的配置说明,请继续讨论。

MIT Licensed