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

相关推荐
liliangcsdn几秒前
smolagents - 如何在mac用agents做简单算术题
人工智能·macos·prompt
Y40900143 分钟前
C语言转Java语言,相同与相异之处
java·c语言·开发语言·笔记
名字不要太长 像我这样就好1 小时前
【iOS】继承链
macos·ios·cocoa
潜龙95272 小时前
第4.3节 iOS App生成追溯关系
macos·ios·cocoa
棐木8 小时前
【C语言】动态内存管理
c语言·free·malloc·realloc·calloc·动态内存
肥or胖11 小时前
【FFmpeg 快速入门】本地播放器 项目
开发语言·qt·ffmpeg·音视频
笑虾11 小时前
bat 批处理实现 FFmpeg 命令导出 mov 到 png 序列帧
ffmpeg·png·mov·序列帧
玄辰星君11 小时前
【MAC】nacos 2.5.1容器docker安装
macos·docker·nacos
屁股割了还要学13 小时前
【C语言进阶】内存函数
c语言·开发语言·学习·算法·青少年编程
耳总是一颗苹果13 小时前
C语言---自定义类型(上)(结构体类型)
c语言·开发语言