macOS上将ffmpeg.c编译成Framework

1 前言

本文介绍下在macOS上将ffmpeg的fftools目录下的ffmpeg.c程序,也就是ffmpeg的命令行程序,编译成framework的方法。编译成.a或.dylib的方法类似。

编译环境如下:

  • xcode15.3;
  • ffmpeg release/6.1;

2 编译ffmpeg

首先clone我们的FFmpeg代码仓到本地,并更名为ffmpeg,切换分支为release/6.1:

复制代码
git clone https://github.com/FFmpeg/FFmpeg.git ffmpeg && git checkout release/6.1

然后在ffmpeg的根目录执行如下命令,由于是学习使用,configure配置的是缺省选项,编译后安装目录在根目录下的mac_build目录下:

复制代码
mkdir -p mac_build && ./configure --prefix=./mac_build

然后执行如下命令,编译并安装ffmpeg:

复制代码
make -j8 && make install

configure并编译安装完成之后,会在根目录下生成如下文件:

  • configure配置完毕,会在根目录产生config.hconfig_components.h文件;
  • 生成了ffmpeg/ffplay/ffprobe可执行文件;
  • mac_build目录是ffmpeg的bin/include/lib/share文件;

其中,mac_build目录结构如下:

复制代码
xxxxxx@localhost:~/Applications/workspace/av/ffmpeg/mac_build$tree -L 2
.
├── bin
│   ├── ffmpeg
│   ├── ffplay
│   └── ffprobe
├── include
│   ├── libavcodec
│   ├── libavdevice
│   ├── libavfilter
│   ├── libavformat
│   ├── libavutil
│   ├── libswresample
│   └── libswscale
├── lib
│   ├── libavcodec.a
│   ├── libavdevice.a
│   ├── libavfilter.a
│   ├── libavformat.a
│   ├── libavutil.a
│   ├── libswresample.a
│   ├── libswscale.a
│   └── pkgconfig
└── share
    ├── ffmpeg
    └── man

15 directories, 10 files

编译安装完成之后,就可以拿该目录下的includelib下的文件引入到工程使用了。

3 编译ffmpeg.c

3.1 新建xcode工程

打开xcode新建一个xcode的app工程:

然后,新建一个target,FFmpegFramework,接着把ffmpeg相关c程序拖进来编译:

然后在FFmpegFramework => Build Settings => Search Paths里加入ffmpeg的includelib以及config.h的搜索路径:

到此,xcode工程和FFmpegFramework的创建和初始化工作完成,接下来就是将FFmpegFramework编译成framework了。

3.2 改写ffmpeg.c的接口方法

  • 在ffmpeg.h文件中,将int main(int argc, char* argv[])方法名改成ffmpeg
  • ffmpeg.c对应文件的main方法名按以上同步修改为ffmpeg

ffmpeg.h头文件中修改方法名:

复制代码
// 将main方法名改为ffmpeg名
int ffmpeg(int argc, char* argv[]);

ffmpeg.c同步修改方法名:

复制代码
// 将main方法名改为ffmpeg
int ffmpeg(int argc, char **argv)
{
    int ret, err_rate_exceeded;
    BenchmarkTimeStamps ti;

    init_dynload();

    setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */

    av_log_set_flags(AV_LOG_SKIP_REPEATED);
    parse_loglevel(argc, argv, options);

#if CONFIG_AVDEVICE
    avdevice_register_all();
#endif
    avformat_network_init();

    show_banner(argc, argv, options);

    /* parse options and open all input/output files */
    ret = ffmpeg_parse_options(argc, argv);
    if (ret < 0)
        goto finish;

    if (nb_output_files <= 0 && nb_input_files == 0) {
        show_usage();
        av_log(NULL, AV_LOG_WARNING, "Use -h to get full help or, even better, run 'man %s'\n", program_name);
        ret = 1;
        goto finish;
    }

    if (nb_output_files <= 0) {
        av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n");
        ret = 1;
        goto finish;
    }

    current_time = ti = get_benchmark_time_stamps();
    ret = transcode(&err_rate_exceeded);
    if (ret >= 0 && do_benchmark) {
        int64_t utime, stime, rtime;
        current_time = get_benchmark_time_stamps();
        utime = current_time.user_usec - ti.user_usec;
        stime = current_time.sys_usec  - ti.sys_usec;
        rtime = current_time.real_usec - ti.real_usec;
        av_log(NULL, AV_LOG_INFO,
               "bench: utime=%0.3fs stime=%0.3fs rtime=%0.3fs\n",
               utime / 1000000.0, stime / 1000000.0, rtime / 1000000.0);
    }

    ret = received_nb_signals ? 255 :
          err_rate_exceeded   ?  69 : ret;

finish:
    if (ret == AVERROR_EXIT)
        ret = 0;

    ffmpeg_cleanup(ret);
    return ret;
}

3.3 将ffmpeg.c编译成Framework

接下来就是将ffmpeg.c编译成framework了,期间遇到了很多问题,但基本是一类问题,那就是链接时的Undefined symbol

解决方式就是将ffmpeg.c所依赖的macOS系统framework和基础.a或者.dylib库链接到本framework即可。如下图,总共依赖了39个库,其中SDL2需用dylib库(若使用libSDL2.a则会报错找不到_FFCreateDevice symbol等):

ffmpeg.c所依赖的.a和.dylib库路径:

复制代码
mingo@localhost:~/Applications/workspace/av/ffmpeg/mac_build/lib$ll
total 292680
drwxr-xr-x  23 mingo  staff       736  5 10 23:58 ./
drwxr-xr-x   7 mingo  staff       224  5 10 11:38 ../
-rw-r--r--@  1 mingo  staff      6148  5 10 23:51 .DS_Store
-r--r--r--   1 mingo  staff   2514640  5 10 23:33 libSDL2.a
-rw-r--r--@  1 mingo  staff   1561488  5 10 23:58 libSDL2.dylib
-r--r--r--   1 mingo  staff       848  5 10 22:49 libX11-xcb.a
-r--r--r--   1 mingo  staff   1402392  5 10 22:49 libX11.a
-r--r--r--   1 mingo  staff     11656  5 10 23:25 libXau.a
-r--r--r--   1 mingo  staff     20696  5 10 23:27 libXdmcp.a
-rw-r--r--   1 mingo  staff  78648416  5 10 11:35 libavcodec.a
-rw-r--r--   1 mingo  staff    574072  5 10 11:35 libavdevice.a
-rw-r--r--   1 mingo  staff  22947096  5 10 11:35 libavfilter.a
-rw-r--r--   1 mingo  staff  26952064  5 10 11:35 libavformat.a
-rw-r--r--   1 mingo  staff   3054552  5 10 11:35 libavutil.a
-r--r--r--   1 mingo  staff   7380136  5 10 22:27 libcrypto.a
-r--r--r--   1 mingo  staff   1386648  5 10 22:24 libssl.a
-rw-r--r--   1 mingo  staff    411520  5 10 11:35 libswresample.a
-rw-r--r--   1 mingo  staff   2655320  5 10 11:35 libswscale.a
-r--r--r--   1 mingo  staff     11160  5 10 22:47 libxcb-shape.a
-r--r--r--   1 mingo  staff      8864  5 10 22:45 libxcb-shm.a
-r--r--r--   1 mingo  staff     39352  5 10 22:43 libxcb-xfixes.a
-r--r--r--   1 mingo  staff    218768  5 10 21:31 libxcb.a
drwxr-xr-x   9 mingo  staff       288  5 10 11:35 pkgconfig/
mingo@localhost:~/Applications/workspace/av/ffmpeg/mac_build/lib$

ffmpeg.c所依赖的macOS系统库及ffmpeg相关库39个:

按以上操作,便可顺利编译FFmpegFramework了。接下来就可以在learn-ffmpeg项目中使用它了。

4 使用framework

贴出main.m调用ffmpeg.c接口的代码:

复制代码
#include "libavutil/log.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavutil/opt.h"
#include "ffmpeg.h"

static void test_ffmpeg(int argc, const char* argv[]) {
    ffmpeg(argc, argv);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // Setup code that might create autoreleased objects goes here.
        av_log_set_level(AV_LOG_DEBUG);
        av_log(NULL, AV_LOG_INFO, "hello ffmpeg");
        // 示例ffmpeg -h命令
        const char* args[] = { "ffmpeg", "-h" };
        test_ffmpeg(2, args);
    }
    return NSApplicationMain(argc, argv);
}

然后,选中learn-ffmpeg target,在learn-ffmpeg => Build Settings => Search Paths => Header Search Paths/Library Search Paths中指定ffmpeg及其framework相关的includelib文件:

include搜索路径:

lib搜索路径:

learn-ffmpeg target中 Build Settings => Link Binary with Library中加入FFmpegFramework

接下来就可以顺利编译learn-ffmpeg程序,并开始调试ffmpeg.c程序了:

相关推荐
小溪彼岸17 小时前
macOS自带截图命令ScreenCapture
macos
小莞尔1 天前
【51单片机】【protues仿真】基于51单片机的篮球计时计分器系统
c语言·stm32·单片机·嵌入式硬件·51单片机
TESmart碲视1 天前
Mac 真正多显示器支持:TESmart USB-C KVM(搭载 DisplayLink 技术)如何实现
macos·计算机外设·电脑
小莞尔1 天前
【51单片机】【protues仿真】 基于51单片机八路抢答器系统
c语言·开发语言·单片机·嵌入式硬件·51单片机
liujing102329291 天前
Day03_刷题niuke20250915
c语言
第七序章1 天前
【C++STL】list的详细用法和底层实现
c语言·c++·自然语言处理·list
l1t1 天前
利用DeepSeek实现服务器客户端模式的DuckDB原型
服务器·c语言·数据库·人工智能·postgresql·协议·duckdb
l1t1 天前
利用美团龙猫用libxml2编写XML转CSV文件C程序
xml·c语言·libxml2·解析器
2501_915106321 天前
Xcode 上传 ipa 全流程详解 App Store 上架流程、uni-app 生成 ipa 文件上传与审核指南
android·macos·ios·小程序·uni-app·iphone·xcode
Gu_shiwww2 天前
数据结构8——双向链表
c语言·数据结构·python·链表·小白初步