前言
最近攤上了視頻監控項目,一想到的就是ffmpeg這個Diao炸天的開源框架,但是這么拽的框架也不是一般人能駕馭得了的,還好有一群二班的人(Bilibili)基于ffmpeg封裝了IJKPlayer,一樣是開源的,但...是這個拽的框架也不是一般人能輕易編譯成功的,所以有了三班的我來協助大家一同過五關斬六將來獲得IJKMediaFramework.framework。
ijkplayer git網址:https://github.com/Bilibili/ijkplayer.git
附上我編譯的framework:鏈接:IJKPlayer_Framework 密碼:gw32
1、戰前準備(Homebrew、git、yasm)
Homebrew:簡稱brew,OSX上必備的軟件包管理工具
ruby -e"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Git:代碼管理工具
brew install git
Yasm:輸出二進制的匯編器
brew install yasm
備注:如之前已安裝過可以忽略,或如下命令檢查是否有安裝:
$ brew -v
Homebrew 1.7.1
Homebrew/homebrew-core (git revision 0c3af; last commit 2018-08-05)
$ git --version
git version 2.18.0
$ yasm --version
yasm 1.3.0
Compiled on Sep 15 2017.
Copyright (c) 2001-2014 Peter Johnson and other Yasm developers.
Run yasm --license for licensing overview and summary.
2、下載IJKPlayer
1、終端打開要存放ijkplayer項目的目錄文件夾,并將代碼克隆到本地:
//進入該目錄中
$cd ~/文件夾
//克隆項目
$git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-ios
//進入ijkplayer-ios
$cd ijkplayer-ios
//切換分支
$git checkout -B latest k0.8.8
備注:如有Git軟件工具“Github、SourceTree”替代,可忽略以上命令
2、正常情況如下:
$ git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-ios
Cloning into 'ijkplayer-ios'...
remote: Counting objects: 24677, done.
Receiving objects: 100% (24677/24677), 7.81 MiB | 5.00 KiB/s, done.
remote: Total 24677 (delta 0), reused 0 (delta 0), pack-reused 24677
Resolving deltas: 100% (15703/15703), done.
$ cd /ijkplayer-ios
wangtingxiedeMacBook-Pro:ijkplayer-ios wangtingxie$ git checkout -B latest k0.8.8
Switched to a new branch 'latest'
3、配置支持RTSP
1、修改module-lite.sh文件
目錄:~/config/module-lite.sh 將這一行:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=rtp"
修改為:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtp"
接著在下面添加上:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=rtsp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=tcp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=mjpeg"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mjpeg"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-openssl" (不需要https請忽略)
2、模塊選擇
//進入ijkplayer / config 目錄
$ cd config
//移除module.sh文件
$ rm module.sh
//替換模塊
$ ln -s module-lite.sh module.sh
備注:可根據具體情況加載模塊:
偏好更多的解碼器/視頻格式支持, 則鏈接module-default.sh
偏好打包出來的庫體積更小 (默認格式支持), 則鏈接module-lite.sh
偏好打包出來的庫體積更小 (包含HEVC支持), 則鏈接module-lite-hevc.sh
3、修改ff_ffplay.c文件
目錄:~/ijkmedia/ijkplayer/ff_ffplay 將這一方法:
static int packet_queue_get_or_buffering(FFPlayer *ffp, PacketQueue *q, AVPacket *pkt, int *serial, int *finished)
{
? ? assert(finished);
? ? if (!ffp->packet_buffering)
? ? ? ? return packet_queue_get(q, pkt, 1, serial);
? ? while (1) {
? ? ? ? int new_packet = packet_queue_get(q, pkt, 0, serial);
? ? ? ? if (new_packet < 0)
? ? ? ? ? ? return -1;
? ? ? ? else if (new_packet == 0) {
? ? ? ? ? ? if (q->is_buffer_indicator && !*finished)
? ? ? ? ? ? ? ? ffp_toggle_buffering(ffp, 1);
? ? ? ? ? ? new_packet = packet_queue_get(q, pkt, 1, serial);
? ? ? ? ? ? if (new_packet < 0)
? ? ? ? ? ? ? ? return -1;
? ? ? ? }
? ? ? ? if (*finished == *serial) {
? ? ? ? ? ? av_packet_unref(pkt);
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ? else
? ? ? ? ? ? break;
? ? }
? ? return 1;
}
修改為:
static int packet_queue_get_or_buffering(FFPlayer *ffp, PacketQueue *q, AVPacket *pkt, int *serial, int *finished){
? ? if (!ffp->packet_buffering)
? ? ? ? return packet_queue_get(q, pkt, 1, serial);
? ? while (1) {
? ? ? ? int new_packet = packet_queue_get(q, pkt, 1, serial);
? ? ? ? if (new_packet < 0){
? ? ? ? ? ? new_packet = packet_queue_get(q, pkt, 0, serial);
? ? ? ? ? ? if(new_packet < 0)
? ? ? ? ? ? ? ? return -1;
? ? ? ? }else if (new_packet == 0) {
? ? ? ? ? ? if (q->is_buffer_indicator && !*finished)
? ? ? ? ? ? ? ? ffp_toggle_buffering(ffp, 1);
? ? ? ? ? ? new_packet = packet_queue_get(q, pkt, 1, serial);
? ? ? ? ? ? if (new_packet < 0)
? ? ? ? ? ? ? ? return -1;
? ? ? ? }
? ? ? ? if (*finished == *serial) {
? ? ? ? ? ? av_packet_unref(pkt);
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ? else
? ? ? ? ? ? break;
? ? }
? ? return 1;
}
4、下載ffmpeg并編譯
1、執行ijkplayer目錄下初始化ios腳本
$ ./init-ios.sh
$ ./init-ios-openssl.sh (不需要https請忽略openssl)
備注:ffmpeg比較大,而且又是國外網絡,腳本運行需要一點時間,遇到失敗需要多試幾次, 等待操作完成, 再繼續
2、編譯ffmpeg
$ cd ios
$ ./compile-ffmpeg.sh clean
$ ./compile-openssl.sh all?(不需要https請忽略openssl)
$ ./compile-ffmpeg.sh all
3、解決遇到的錯誤
錯誤1:
xcrun -sdk iphoneos clang is unable to create an executable file.
C compiler test failed.
If you think configure made a mistake, make sure you are using the latest
version from Git.? If the latest version fails, report the problem to the
ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "ffbuild/config.log" produced by configure as this will help
solve the problem.
解決方法:sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer/
錯誤2:
AS??? libavcodec/arm/aacpsdsp_neon.o
./libavutil/arm/asm.S:50:9: error: unknown directive
??????? .arch armv7-a
??????? ^
make: *** [libavcodec/arm/aacpsdsp_neon.o] Error 1
make: *** Waiting for unfinished jobs....原因:最新的 Xcode 已經弱化了對 32 位的支持。
解決方法:修改./compile-ffmpeg.sh文件,
將這一行:FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64"
修改為:FF_ALL_ARCHS_IOS8_SDK="arm64 i386 x86_64"
再重新執行出現錯誤的命令: ./compile-ffmpeg.sh all
錯誤3:'openssl/ssl.h' file not found
#include <openssl/ssl.h> ERROR: openssl not found原因:編譯ffmpeg軟解碼庫,這個過程會生成各種架構的ffmpeg,編譯ffmpeg前要先compile OpenSSL,對openssl進行編譯,如果未執行可能會報錯。必須先執行./compile-openssl.sh all
因為兼容指令集比較多,編譯會比較慢一點,我們也可以只編譯一個指令集版本(便于調試)
$ ./compile-ffmpeg.sh all x86_64
5、打包 framwork并合并
大家會發現除了IJKMediaFramework這個 target, 還有一個叫IJKMediaFrameworkWithSSL, 但是不推薦使用這個, 因為大部分基于 ijkplayer 的第三方框架都是使用的前者, 你把后者導入項目還是會報找不到包的錯誤, 就算你要支持 https 也推薦使用前者, 然后按照上一步添加 openssl 即可支持
1、配置 Release 模式如下圖
2、打包真機 framework
選擇Generic iOS Device
如圖操作,然后按鍵command+b編譯即可
如果之前的步驟刪除了compile-ffmpeg.sh中armv7, 這里會報錯, 我們直接注釋掉就好
3、打包模擬器 framework
如圖操作,然后command+b編譯即可
4、合并 framework
如果只需要真機運行或者模擬器運行, 可以不用合并, 直接找到對應的 framework 導入項目即可; 一般我們為了方便會合并 framework, 這樣就同時支持模擬器和真機運行.
先找到生成 framework 的目錄:
準備合并:
打開終端, 先cd到Products目錄下
然后執行:lipo -create 真機framework路徑 模擬器framework路徑 -output 合并的文件路徑
lipo -create Release-iphoneos/IJKMediaFramework.framework/IJKMediaFramework Release-iphonesimulator/IJKMediaFramework.framework/IJKMediaFramework -output IJKMediaFramework
合并完成:
可以看到這里生成了一個大概兩倍大小的文件, 將生成的IJKMediaFramework文件替換掉真機framework中的IJKMediaFramework文件,然后這個替換掉文件的真機framework就是我們需要的通用的framework了。
6、集成 framework 到項目中
導入 framework
直接將IJKMediaFramework.framework拖入到工程中即可
注意記得勾選Copy items if needed和 對應的target
7、添加下列依賴到工程
libc++.tbd( 編譯器選 gcc 的請導入libstdc++.tbd)
libz.tbd
libbz2.tbd
AudioToolbox.framework
UIKit.framework
CoreGraphics.framework
AVFoundation.framework
CoreMedia.framework
CoreVideo.framework
MediaPlayer.framework
MobileCoreServices.framework
OpenGLES.framework
QuartzCore.framework
VideoToolbox.framework
導入 ijkplayer 頭文件運行一下項目, 如果遇到了類似這樣的錯誤:
可能是因為導入的依賴庫不全, 比如缺少 libc++.tbd, 請再次對照添加好所有的依賴庫:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mjpeg"