当前位置: 首页 > 工具软件 > kxmovie > 使用案例 >

iOS ffmpeg kxmovie 编译 调试 /最新 ffmpeg2.5.3/iOS SDK8.1/XCODE6.1/

仲孙小云
2023-12-01

1.下载ffmpeg源码

ffmpeg官网下载最新tarball v.2.5.3

http://ffmpeg.org/download.html

或者你可以淘个history version

http://ffmpeg.org/releases/


2. ffmpeg:直接编译or间接编译?


1)直接编译:

ffmpeg官方wiki对iOS 平台木有太大帮助

可以看看涨姿势

http://trac.ffmpeg.org/wiki

so..只能自己找bash编译

google被墙 但是git人品好

搜索 iOS build-ffmpeg

立马出几页脚本

找最新的

对各平台最新ios最新sdk最新ffmpeg都支持的

我用的是

https://github.com/kewlbear/FFmpeg-iOS-build-script

15/1/12 updated

平台:iOS SDK8.1/XCODE6.1/ffmpeg2.5.3

直接sh build-ffmpeg.sh

一马平川 无坚不摧

脚本写的很简洁 valuable

别的脚本年少无知的时候

都试过好几个

大多是出bug或者只能支持低版本

需要注意gas-preprocessor.pl这个pearl脚本非常重要

需要保证updated

可以在闹政变独立出来的libav的git主页找到

建议master版

https://github.com/libav/gas-preprocessor

 1、拷贝gas-preprocessor.pl文件到 /usr/bin 和 /usr/local/bin 目录下。
 2、修改gas-preprocessor.pl文件的权 使用 chmod a+rwx gas-preprocessor.pl

还有就是要下载yasm

用curl下载

sudo curl http://www.tortall.net/projects/yasm/releases/yasm-1.2.0.tar.gz >yasm.tar.gz

当然 可以直接进入release list下载tar ball

任何历史版本都有

http://www.tortall.net/projects/yasm/releases/

建议最新版

因为build-shell.sh要求yasm达到1.2 or later

不装yasm的后果是编译的时候会提示你

./configure --disable-yasm

当然这两步也不是必须的

因为咱有脚本~

脚本的作用就是帮你做你会疏忽的事儿

当你没做这些事的时候

bash会一步步去check configure

然后在shell运行的时候提出相应的建议

看看build-shell.sh就知道了~


2)间接编译

由于要做字幕控制播放进度

用kxmovie做模板

这个项目比较全能

里面的rakefile可以完成:

a)编译ffmpeg静态库

b)编译kxmovie静态库

c)编译kxmovie源码和测试项目

三项功能

所以学习大牛脚本非常重要

但是大牛往往写脚本都不注释

所以必须自己研读

读完之后还是非常清晰的

虽然众多task都没用上

对这份脚本做了customization

使得也能适配最新的ffmpeg2.5.3

当然个中过程曲折离奇

都说要选比较陈旧的版本编译

可以避免许多bugs

但是

非亲身体验新版

无法体会到编译的乐趣

我的定制在rakefile里都做了注释

大家可以参考

可惜的是想打包libass进去

但是貌似没有移动端的libass

字幕的问题日后在研究


3.编译kxmovie

KXMOVIE PLAYER:

https://github.com/kolyvan/kxmovie

由于调用了ffmpeg的静态库

而且kxmovie本身也调用超Q多库

所以过程非常曲折

由于有了N个开源播放器编译失败的经验

也见怪不怪

一点一点的trace

在改好rakefile之后可以直接调用里面的build_kxmovie_released

或者build_kxmovie_debug直接生成libkxmovie.a

按照readme.md里的示例代码并设置头文件和库路径之后

可以直接在第三方软件调用静态库

但是直接在kxmovie项目中有问题

xcode的特点就是几乎所有问题都是linker问题


1)爆了_logMessageF cannot be referenced 

这个bug中的_logMessageF可以直接通过command+click找到

这就非常奇怪

后来在项目中的Pods/NSLogger/ios里找到源文件

把源文件添加到项目中就OK了


2)爆了 AVCaptureVideoDataOutput cannot be referenced 

AVCaptureVideoDataOutput在项目中并未涉及

这是个libavdevice.a里的一个.m文件调用到的类

属于摄像头调用

在源码中引用了AVFoundation.h

所以 除了readme中提到的包

还要在项目中导入包含此头文件的framework

AVFoundation.framework


之后就OK了




综合整个过程是非常波折的

这里只表达了万一

各种调各种改

更多的反映在脚本中



这里要鸣谢妙心

http://blog.csdn.net/oqqQuZi1234567/article/details/43152689

这篇blog有很大的的启发


大家有疑问的欢迎交流

下面附上RakeFile

<span style="font-size:14px;">require "pathname"
require "fileutils"

def system_or_exit(cmd, stdout = nil)
  puts "Executing #{cmd}"
  cmd += " >#{stdout}" if stdout
  system(cmd) or raise "******** Build failed ********"
end

## build ffmpeg

SDK_VERSION='8.1'
MIN_IOS_VERSION='7.0'

XCODE_PATH='/Applications/Xcode.app/Contents/Developer/Platforms'
GCC_PATH='/Applications/XCode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang'
LIB_PATH='/usr/lib/system'
GASPREP_DEST_PATH='/usr/local/bin'
PLATOFRM_PATH_SIM ='/iPhoneSimulator.platform'
PLATOFRM_PATH_IOS ='/iPhoneOS.platform'
SDK_PATH_SIM="/Developer/SDKs/iPhoneSimulator#{SDK_VERSION}.sdk"
SDK_PATH_IOS="/Developer/SDKs/iPhoneOS#{SDK_VERSION}.sdk"
SIM_SDK = 'iphonesimulator' +  SDK_VERSION
IOS_SDK = 'iphoneos' + SDK_VERSION


FFMPEG_BUILD_ARGS_SIM = [
'--assert-level=2',
'--disable-mmx',
'--arch=i386',
'--cpu=i386',
"--extra-ldflags='-arch i386 -miphoneos-version-min=#{MIN_IOS_VERSION}'",
"--extra-cflags='-arch i386 -miphoneos-version-min=#{MIN_IOS_VERSION}'",
'--disable-asm',
]

#添加SDK根目录-isysroot 
#修改MIN_IOS_VERSION对齐kxmovie
FFMPEG_BUILD_ARGS_ARMV7 = [
'--arch=arm',
'--cpu=cortex-a8',
'--enable-pic',
"--extra-cflags='-arch armv7 -miphoneos-version-min=#{MIN_IOS_VERSION}'",
"--extra-ldflags='-arch armv7 -miphoneos-version-min=#{MIN_IOS_VERSION}'",
"--extra-cflags='-mfpu=neon -mfloat-abi=softfp'",
'--enable-neon',
# '--disable-neon',
'--enable-optimizations',
'--disable-debug',
'--disable-armv5te',
'--disable-armv6',
'--disable-armv6t2',
'--enable-small',
]

#修改MIN_IOS_VERSION对齐kxmovie
FFMPEG_BUILD_ARGS_ARMV7S = [
'--arch=arm',
'--cpu=cortex-a9',
'--enable-pic',
"--extra-cflags='-arch armv7s -miphoneos-version-min=#{MIN_IOS_VERSION}'",
"--extra-ldflags='-arch armv7s -miphoneos-version-min=#{MIN_IOS_VERSION}'",
"--extra-cflags='-mfpu=neon -mfloat-abi=softfp'",
'--enable-neon',
# '--disable-neon',
'--enable-optimizations',
'--disable-debug',
'--disable-armv5te',
'--disable-armv6',
'--disable-armv6t2',
'--enable-small',
]

#修改MIN_IOS_VERSION对齐kxmovie
FFMPEG_BUILD_ARGS_ARM64 = [
'--arch=arm64',
# '--cpu=cortex-a9',
'--enable-pic',
"--extra-cflags='-arch arm64 -miphoneos-version-min=#{MIN_IOS_VERSION}'",
"--extra-ldflags='-arch arm64 -miphoneos-version-min=#{MIN_IOS_VERSION}'",
"--extra-cflags='-mfpu=neon -mfloat-abi=softfp'",
'--enable-neon',
# '--disable-neon',
'--enable-optimizations',
'--disable-debug',
'--disable-armv5te',
'--disable-armv6',
'--disable-armv6t2',
'--enable-small',
]

FFMPEG_BUILD_ARGS = [
'--disable-ffmpeg',
'--disable-ffplay',
'--disable-ffserver',
'--disable-ffprobe',
'--disable-doc',
'--disable-bzlib',
'--target-os=darwin',
'--enable-cross-compile',
#'--enable-nonfree',
# '--enable-gpl',
'--enable-version3',
]

#补全缺少的库
FFMPEG_LIBS = [
'libavcodec',
'libavformat',
'libavutil',
'libswscale',
'libswresample',
'libavfilter',
'libswscale',
'libavdevice',
]

def mkArgs(arch, platformPath, sdkPath, platformArgs)
	#不必设定安装路径
	#库和头文件会自动安装到/usr/local
	#prefix = '--prefix=' + arch
	cc = '--cc=' + GCC_PATH
	#这个as是脚本gas-preprocessor.pl的地址,放到bin之后编译时并不需要
	as = ""
	sysroot = '--sysroot=' + XCODE_PATH + platformPath + sdkPath
	#extra = '--extra-ldflags=-L' + XCODE_PATH + platformPath + sdkPath + LIB_PATH
	args = FFMPEG_BUILD_ARGS + platformArgs
	# args << prefix
	args << cc 
	args << as
	args << sysroot
	
	args.join(' ')
end

#move改为copy
#新版本ffmpeg静态库之间有依赖,move之后会找不到库报错
def copyLibs(dest)
	FFMPEG_LIBS.each do |x|
		FileUtils.copy Pathname.new("FFmpeg/#{x}/#{x}.a"), dest		
	end
end

def ensureDir(path)

	dest = Pathname.new path
	if dest.exist?
		FileUtils.rm Dir.glob("#{path}/*.a")
	else
		dest.mkpath
	end

	dest
end

def buildArch(arch)

	case arch
	when 'i386'
		args = mkArgs(arch, PLATOFRM_PATH_SIM, SDK_PATH_SIM, FFMPEG_BUILD_ARGS_SIM)
	when 'armv7'
		args = mkArgs(arch, PLATOFRM_PATH_IOS, SDK_PATH_IOS, FFMPEG_BUILD_ARGS_ARMV7)
	when 'armv7s'
		args = mkArgs(arch, PLATOFRM_PATH_IOS, SDK_PATH_IOS, FFMPEG_BUILD_ARGS_ARMV7S)		
	when 'arm64'
		args = mkArgs(arch, PLATOFRM_PATH_IOS, SDK_PATH_IOS, FFMPEG_BUILD_ARGS_ARM64)		
	else
		raise "Build failed: unknown arch: #{arch}"
	end
	
	dest = ensureDir('FFmpeg/' + arch)
	
	system_or_exit "cd FFmpeg; ./configure #{args}"
	system_or_exit "cd FFmpeg; make"	
	copyLibs(dest)	
	system_or_exit "cd FFmpeg; [ -f -.d ] && rm -- -.d; make clean"

end

#补全lipo对各架构的支持,修改原-arch参数错误
def mkLipoArgs(lib)
	"-create -arch armv7 armv7/#{lib}.a -arch armv7s armv7s/#{lib}.a -arch arm64 arm64/#{lib}.a -arch i386 i386/#{lib}.a -output universal/#{lib}.a"
end

desc "check gas-preprocessor.pl"
task :check_gas_preprocessor do	

	found = false

	ENV['PATH'].split(':').each do |x|
		p = Pathname.new(x) + 'gas-preprocessor.pl'
		if p.exist? && p.writable?
			found = true
			break;
		end
	end

	unless found
    # See http://stackoverflow.com/questions/5056600/how-to-install-gas-preprocessor for more info.
    puts "Installing the gas-preprocessor to #{GASPREP_DEST_PATH}"
    
    FileUtils.move Pathname.new("gas-preprocessor/gas-preprocessor.pl"), Pathname.new(GASPREP_DEST_PATH)
  	system_or_exit "chmod +x #{GASPREP_DEST_PATH}/gas-preprocessor.pl"
    
    # raise "Build failed: first install gas-preprocessor.pl.\nSee http://stackoverflow.com/questions/5056600/how-to-install-gas-preprocessor for more info."
	end

end

desc "Clean ffmpeg"
task :clean_ffmpeg do
	system_or_exit "cd FFmpeg; [ -f -.d ] && rm -- -.d; make clean"
end

desc "Build ffmpeg i386 libs"
task :build_ffmpeg_i386 do	
	buildArch('i386')	
end

desc "Build ffmpeg armv7 libs"
task :build_ffmpeg_armv7 do	
	buildArch('armv7')	
end

desc "Build ffmpeg armv7s libs"
task :build_ffmpeg_armv7s do	
	buildArch('armv7s')	
end

desc "Build ffmpeg arm64 libs"
task :build_ffmpeg_arm64 do	
	buildArch('arm64')	
end

#move改为copy
#新版本ffmpeg静态库之间有依赖,move之后会找不到库报错
desc "Build ffmpeg universal libs"
task :build_ffmpeg_universal do	

	dest = ensureDir('FFmpeg/universal/')
	FFMPEG_LIBS.each do |x|
		args = mkLipoArgs(x)
		system_or_exit "cd FFmpeg; xcrun -sdk iphoneos lipo #{args}"
	end

	# FileUtils.cp 'FFmpeg/armv7/include/', dest

	dest = ensureDir('libs/')
	FFMPEG_LIBS.each do |x|
		FileUtils.copy Pathname.new("FFmpeg/universal/#{x}.a"), dest
	end

	# FileUtils.cp 'FFmpeg/universal/include/', '.'

end

## build libkxmovie

def cleanMovieLib(config)
	buildDir = Pathname.new 'tmp/build'	
  	system_or_exit "xcodebuild -project kxmovie.xcodeproj -target kxmovie -configuration #{config} -sdk iphoneos#{SDK_VERSION} clean SYMROOT=#{buildDir}"
	system_or_exit "xcodebuild -project kxmovie.xcodeproj -target kxmovie -configuration #{config} -sdk iphonesimulator#{SDK_VERSION} clean SYMROOT=#{buildDir}"  	
end

desc "Clean libkxmovie-debug"
task :clean_movie_debug do
	cleanMovieLib 'Debug'
end

desc "Clean libkxmovie-release"
task :clean_movie_release do
	cleanMovieLib 'Release'
end

#创建三个真机架构下的库文件和32位模拟器下的库文件
#我修改了目标目录
#删除模拟器库文件的-arch参数
#避免lipo爆错:architectures can't be specifed for fat input files
desc "Build libkxmovie-debug"
task :build_movie_debug do
	buildDir = Pathname.new 'tmp/build'
	system_or_exit "xcodebuild -project kxmovie.xcodeproj -target kxmovie -configuration Debug -sdk iphoneos#{SDK_VERSION} build SYMROOT=#{buildDir} -arch armv7"			
	FileUtils.move Pathname.new('tmp/build/Debug-iphoneos/libkxmovie.a'), Pathname.new('tmp/build/Debug-iphoneos/libkxmovie_armv7.a')	

	system_or_exit "xcodebuild -project kxmovie.xcodeproj -target kxmovie -configuration Debug -sdk iphoneos#{SDK_VERSION} build SYMROOT=#{buildDir} -arch armv7s"
	FileUtils.move Pathname.new('tmp/build/Debug-iphoneos/libkxmovie.a'), Pathname.new('tmp/build/Debug-iphoneos/libkxmovie_armv7s.a')

	system_or_exit "xcodebuild -project kxmovie.xcodeproj -target kxmovie -configuration Debug -sdk iphoneos#{SDK_VERSION} build SYMROOT=#{buildDir} -arch arm64"			
	FileUtils.move Pathname.new('tmp/build/Debug-iphoneos/libkxmovie.a'), Pathname.new('tmp/build/Debug-iphoneos/libkxmovie_arm64.a')	

	system_or_exit "xcodebuild -project kxmovie.xcodeproj -target kxmovie -configuration Debug -sdk iphonesimulator#{SDK_VERSION} build SYMROOT=#{buildDir}"
	system_or_exit "lipo -create -arch armv7 tmp/build/Debug-iphoneos/libkxmovie_armv7.a -arch armv7s tmp/build/Debug-iphoneos/libkxmovie_armv7s.a -arch arm64 tmp/build/Debug-iphoneos/libkxmovie_arm64.a tmp/build/Debug-iphonesimulator/libkxmovie.a -output libs/libkxmovie.a"
end

#创建三个真机架构下的库文件和32位模拟器下的库文件
#我修改了目标目录
#删除模拟器库文件的-arch参数
#避免lipo爆错:architectures can't be specifed for fat input files
desc "Build libkxmovie-release"
task :build_movie_release do
	buildDir = Pathname.new 'tmp/build'

	system_or_exit "xcodebuild -project kxmovie.xcodeproj -target kxmovie -configuration Release -sdk iphoneos#{SDK_VERSION} build SYMROOT=#{buildDir} -arch armv7"
	FileUtils.move Pathname.new('tmp/build/Release-iphoneos/libkxmovie.a'), Pathname.new('tmp/build/Release-iphoneos/libkxmovie_armv7.a')	

	system_or_exit "xcodebuild -project kxmovie.xcodeproj -target kxmovie -configuration Release -sdk iphoneos#{SDK_VERSION} build SYMROOT=#{buildDir} -arch armv7s"	
	FileUtils.move Pathname.new('tmp/build/Release-iphoneos/libkxmovie.a'), Pathname.new('tmp/build/Release-iphoneos/libkxmovie_armv7s.a')	

	system_or_exit "xcodebuild -project kxmovie.xcodeproj -target kxmovie -configuration Release -sdk iphoneos#{SDK_VERSION} build SYMROOT=#{buildDir} -arch arm64"	
	FileUtils.move Pathname.new('tmp/build/Release-iphoneos/libkxmovie.a'), Pathname.new('tmp/build/Release-iphoneos/libkxmovie_arm64.a')

	system_or_exit "xcodebuild -project kxmovie.xcodeproj -target kxmovie -configuration Debug -sdk iphonesimulator#{SDK_VERSION} build SYMROOT=#{buildDir}"	
	system_or_exit "lipo -create -arch armv7 tmp/build/Release-iphoneos/libkxmovie_armv7.a -arch armv7s tmp/build/Release-iphoneos/libkxmovie_armv7s.a -arch arm64 tmp/build/Release-iphoneos/libkxmovie_arm64.a tmp/build/Debug-iphonesimulator/libkxmovie.a -output libs/libkxmovie.a"
end

#Deprecated by myself
desc "Copy to output folder"
task :copy_movie do	
	dest = ensureDir 'output'
	FileUtils.move Pathname.new('tmp/build/libkxmovie.a'), dest		
	FileUtils.copy Pathname.new('libs/FFmpeg/libavcodec.a'), dest
	FileUtils.copy Pathname.new('libs/FFmpeg/libavformat.a'), dest
	FileUtils.copy Pathname.new('libs/FFmpeg/libavutil.a'), dest
	FileUtils.copy Pathname.new('libs/FFmpeg/libswscale.a'), dest
	FileUtils.copy Pathname.new('libs/FFmpeg/libswresample.a'), dest
	FileUtils.copy Pathname.new('kxmovie/KxMovieViewController.h'), dest	
	FileUtils.copy Pathname.new('kxmovie/KxAudioManager.h'), dest	
	FileUtils.copy Pathname.new('kxmovie/KxMovieDecoder.h'), dest
	FileUtils.copy_entry Pathname.new('kxmovie/kxmovie.bundle'), dest + 'kxmovie.bundle'
end	

##
task :clean => [:clean_movie_debug, :clean_movie_release, :clean_ffmpeg]
task :build_ffmpeg => [:check_gas_preprocessor, :build_ffmpeg_armv7, :build_ffmpeg_armv7s, :build_ffmpeg_arm64, :build_ffmpeg_i386, :build_ffmpeg_universal]
#task :build_movie => [:build_movie_debug, :copy_movie] 
task :build_movie => [:build_movie_release, :copy_movie] 
task :build_all => [:build_ffmpeg, :build_movie] 
# task :default => [:build_all]
#自定义的入口,可DIY
task :default => [:build_ffmpeg, :build_movie_release]
</span>



 类似资料: