前言
最近攤上了視頻監(jiān)控項(xiàng)目,一想到的就是ffmpeg這個(gè)Diao炸天的開源框架,但是這么拽的框架也不是一般人能駕馭得了的,還好有一群二班的人(Bilibili)基于ffmpeg封裝了IJKPlayer,一樣是開源的,但...是這個(gè)拽的框架也不是一般人能輕易編譯成功的,所以有了三班的我來協(xié)助大家一同過五關(guān)斬六將來獲得IJKMediaFramework.framework。
ijkplayer git網(wǎng)址:https://github.com/Bilibili/ijkplayer.git
附上我編譯的framework:鏈接:IJKPlayer_Framework 密碼:gw32
1、戰(zhàn)前準(zhǔn)備(Homebrew、git、yasm)
Homebrew:簡稱brew,OSX上必備的軟件包管理工具
ruby -e"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Git:代碼管理工具
brew install git
Yasm:輸出二進(jìn)制的匯編器
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項(xiàng)目的目錄文件夾,并將代碼克隆到本地:
//進(jìn)入該目錄中
$cd ~/文件夾
//克隆項(xiàng)目
$git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-ios
//進(jìn)入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請(qǐng)忽略)
2、模塊選擇
//進(jìn)入ijkplayer / config 目錄
$ cd config
//移除module.sh文件
$ rm module.sh
//替換模塊
$ ln -s module-lite.sh module.sh
備注:可根據(jù)具體情況加載模塊:
偏好更多的解碼器/視頻格式支持, 則鏈接module-default.sh
偏好打包出來的庫體積更小 (默認(rèn)格式支持), 則鏈接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、執(zhí)行ijkplayer目錄下初始化ios腳本
$ ./init-ios.sh
$ ./init-ios-openssl.sh (不需要https請(qǐng)忽略openssl)
備注:ffmpeg比較大,而且又是國外網(wǎng)絡(luò),腳本運(yùn)行需要一點(diǎn)時(shí)間,遇到失敗需要多試幾次, 等待操作完成, 再繼續(xù)
2、編譯ffmpeg
$ cd ios
$ ./compile-ffmpeg.sh clean
$ ./compile-openssl.sh all?(不需要https請(qǐng)忽略openssl)
$ ./compile-ffmpeg.sh all
3、解決遇到的錯(cuò)誤
錯(cuò)誤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/
錯(cuò)誤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 已經(jīng)弱化了對(duì) 32 位的支持。
解決方法:修改./compile-ffmpeg.sh文件,
將這一行:FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64"
修改為:FF_ALL_ARCHS_IOS8_SDK="arm64 i386 x86_64"
再重新執(zhí)行出現(xiàn)錯(cuò)誤的命令: ./compile-ffmpeg.sh all
錯(cuò)誤3:'openssl/ssl.h' file not found
#include <openssl/ssl.h> ERROR: openssl not found原因:編譯ffmpeg軟解碼庫,這個(gè)過程會(huì)生成各種架構(gòu)的ffmpeg,編譯ffmpeg前要先compile OpenSSL,對(duì)openssl進(jìn)行編譯,如果未執(zhí)行可能會(huì)報(bào)錯(cuò)。必須先執(zhí)行./compile-openssl.sh all
因?yàn)榧嫒葜噶罴容^多,編譯會(huì)比較慢一點(diǎn),我們也可以只編譯一個(gè)指令集版本(便于調(diào)試)
$ ./compile-ffmpeg.sh all x86_64
5、打包 framwork并合并
大家會(huì)發(fā)現(xiàn)除了IJKMediaFramework這個(gè) target, 還有一個(gè)叫IJKMediaFrameworkWithSSL, 但是不推薦使用這個(gè), 因?yàn)榇蟛糠只?ijkplayer 的第三方框架都是使用的前者, 你把后者導(dǎo)入項(xiàng)目還是會(huì)報(bào)找不到包的錯(cuò)誤, 就算你要支持 https 也推薦使用前者, 然后按照上一步添加 openssl 即可支持
1、配置 Release 模式如下圖


2、打包真機(jī) framework
選擇Generic iOS Device

如圖操作,然后按鍵command+b編譯即可
如果之前的步驟刪除了compile-ffmpeg.sh中armv7, 這里會(huì)報(bào)錯(cuò), 我們直接注釋掉就好


3、打包模擬器 framework

如圖操作,然后command+b編譯即可
4、合并 framework
如果只需要真機(jī)運(yùn)行或者模擬器運(yùn)行, 可以不用合并, 直接找到對(duì)應(yīng)的 framework 導(dǎo)入項(xiàng)目即可; 一般我們?yōu)榱朔奖銜?huì)合并 framework, 這樣就同時(shí)支持模擬器和真機(jī)運(yùn)行.
先找到生成 framework 的目錄:


準(zhǔn)備合并:
打開終端, 先cd到Products目錄下
然后執(zhí)行:lipo -create 真機(jī)framework路徑 模擬器framework路徑 -output 合并的文件路徑
lipo -create Release-iphoneos/IJKMediaFramework.framework/IJKMediaFramework Release-iphonesimulator/IJKMediaFramework.framework/IJKMediaFramework -output IJKMediaFramework
合并完成:
可以看到這里生成了一個(gè)大概兩倍大小的文件, 將生成的IJKMediaFramework文件替換掉真機(jī)framework中的IJKMediaFramework文件,然后這個(gè)替換掉文件的真機(jī)framework就是我們需要的通用的framework了。


6、集成 framework 到項(xiàng)目中
導(dǎo)入 framework
直接將IJKMediaFramework.framework拖入到工程中即可
注意記得勾選Copy items if needed和 對(duì)應(yīng)的target
7、添加下列依賴到工程
libc++.tbd( 編譯器選 gcc 的請(qǐng)導(dǎo)入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
導(dǎo)入 ijkplayer 頭文件運(yùn)行一下項(xiàng)目, 如果遇到了類似這樣的錯(cuò)誤:

可能是因?yàn)閷?dǎo)入的依賴庫不全, 比如缺少 libc++.tbd, 請(qǐng)?jiān)俅螌?duì)照添加好所有的依賴庫:

export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mjpeg"