目標(biāo)
前段時(shí)間編譯了iOS平臺(tái)的ffmepg,這里記錄一下過(guò)程。
首先是明確目標(biāo):編譯的是x264 + fdk-aac + ffmpeg的iOS庫(kù)
環(huán)境準(zhǔn)備
安裝yasm,brew install yasm
1、編譯x264
1、下載x264的源碼 https://www.videolan.org/developers/x264.html
2、下載github的編譯腳本 https://github.com/kewlbear/x264-ios,根據(jù)自己的架構(gòu)需要,修改腳本
編譯成功后,會(huì)有一個(gè)x264-iOS的文件夾
build-x264.sh
x264的源碼目錄
x264-iOS
- include
- lib
2、編譯fdk-aac
1、下載fdk-aac源碼 https://www.linuxfromscratch.org/blfs/view/svn/multimedia/fdk-aac.html
2、下載github的編譯腳本 https://github.com/kewlbear/fdk-aac-build-script-for-iOS根據(jù)自己的架構(gòu)需要,修改腳本
編譯成功后,會(huì)有一個(gè)fdk-aac-ios的文件夾
build-fdk-aac.sh
fdk-aac-2.0.2的源碼目錄
fdk-aac-ios
- include
- lib
3、編譯ffmpeg
1、下載ffmpeg源碼,https://ffmpeg.org/download.html
2、下載github的編譯腳本 https://github.com/kewlbear/FFmpeg-iOS-build-script
3、修改腳本的x264-iOS,fdk-aac-ios路徑以及ffmpeg版本號(hào)
# directories
FF_VERSION="4.3.2" # 這里改為你下載的sdk版本
#FF_VERSION="snapshot-git"
if [[ $FFMPEG_VERSION != "" ]]; then
FF_VERSION=$FFMPEG_VERSION
fi
SOURCE="ffmpeg-$FF_VERSION"
FAT="FFmpeg-iOS"
SCRATCH="scratch"
# must be an absolute path
THIN=`pwd`/"thin"
# absolute path to x264 library
X264=`pwd`/"x264-iOS" # x264的lib目錄
FDK_AAC=`pwd`/"fdk-aac-ios" # fdk的lib目錄
...
總體的文件目錄是這樣的
build-ffmpeg.sh
x264-ios # x264的lib文件夾
fdk-aac-ios # fdk的lib文件夾
ffmpeg-4.3.2 # ffmpeg的源碼文件夾
FFmpeg-iOS # ffmpeg-iOS編譯產(chǎn)物
-include
-lib
demo驗(yàn)證
xcode新建一個(gè)工程,將x264-iOS, fdk-aac-ios, FFmpeg-iOS ,還有ffmpeg源碼目錄的的fftools的以下文件拖入都工程中:
cmdutils.c ffmpeg.h ffmpeg_videotoolbox.c
cmdutils.h ffmpeg_filter.c mathops.h
config.h ffmpeg_hw.c
ffmpeg.c ffmpeg_opt.c
config.h會(huì)根據(jù)configure的執(zhí)行生成,跟fftool同層
mathops.h在源碼的libavcodec目錄下
根據(jù)編譯提示,注釋這些頭文件
#include "libavutil/thread.h
#include "libswresample/swresample.h"
#include "compat/va_copy.h"
#include "libavutil/libm.h"
...
一個(gè)工程只能有一個(gè)main入口,所以需要修改ffmpeg.c的main函數(shù)為int ffmpeg_main,并且在ffmpeg.h文件聲明一下
// ffmpeg.h
int ffmpeg_main(int argc, char **argv);
編譯通過(guò)后,我們就可以通過(guò)xcode來(lái)執(zhí)行ffmpeg的指令,將mp4生成一個(gè)gif
ffmpeg -i out.mp4 out.gif
對(duì)應(yīng)的iOS代碼,引入ffmpeg.h頭文件,以下路徑是在模擬器跑的,真機(jī)需要修改一下輸出路徑
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"out.mp4" ofType:nil];
NSString *outPath = @"/Users/maple/Desktop/out.gif";
int argc = 4;
char **arguments = (char **)calloc(argc, sizeof(char *));
if(arguments != NULL) {
arguments[0] = "ffmpeg";
arguments[1] = "-i";
arguments[2] = (char *)[filePath UTF8String];
arguments[3] = (char *)[outPath UTF8String];
NSLog(@"rescode=%d", ffmpeg_main(argc, arguments));
}
ffmpeg_main(argc, arguments);
或者通過(guò)這種方式調(diào)用,比較簡(jiǎn)練
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"out.mp4" ofType:nil];
NSString *outPath = @"/Users/maple/Desktop/out.gif";
NSString *cmmondStr = [NSString stringWithFormat:@"ffmpeg -i %@ %@", filePath, outPath];
NSMutableArray *argv_arr = [cmmondStr componentsSeparatedByString:@" "].mutableCopy;
int argc = (int)argv_arr.count;
char **arguments = (char **)calloc(argc, sizeof(char *));
for(int i = 0; i < argc; i++) {
NSString *str = argv_arr[i];
arguments[i] = (char *)[str UTF8String];
}
ffmpeg_main(argc, arguments);
為了不讓ffmpeg_main執(zhí)行完后退出程序,這里注釋了ffmpeg_main函數(shù)的最后一行
exit_program(received_nb_signals ? 255 : main_return_code);