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程序了:

相关推荐
茶猫_4 分钟前
力扣面试题 - 40 迷路的机器人 C语言解法
c语言·数据结构·算法·leetcode·机器人·深度优先
_小柏_1 小时前
C/C++基础知识复习(46)
c语言·开发语言·c++
缘友一世1 小时前
macos安装maven以及.bash_profile文件优化
macos·maven·bash
还是车万大佬3 小时前
面对小白的C语言学习方法
c语言·学习方法
轻口味4 小时前
【每日学点鸿蒙知识】启动耗时分析、IDE报错、emitter内存泄漏、radio C API、SDK下载失败
c语言·华为·harmonyos
阿7_QuQ5 小时前
mac远程控制另一台mac怎么操作?
运维·服务器·macos
Say-hai6 小时前
FFmpeg 的常用API
ffmpeg
A懿轩A7 小时前
C/C++ 数据结构与算法【树和森林】 树和森林 详细解析【日常学习,考研必备】带图+详细代码
c语言·c++·考研·数据结构与算法·树和森林
C语言编程小刘 17 小时前
C语言期末复习1.1
c语言·算法·leetcode
缘友一世7 小时前
MacOS安装Xcode(非App Store)
ide·macos·xcode