ijkplayer框架的集成( 從開始到優化秒開)


 

ijkplayer是bibiliB站開源的一個三方,面向對象開發。

蘋果提供了:AVPlayer播放不了直播文件。需要自己去基於ffmpeg播放。

ijkplayer框架是專門用來做  視頻直播 的開源框架,基於 ffmpeg,同時支持  Android 和  iOS 平台。
對於 App 中的直播功能,集成 ijkplayer ,那么就算完成一半的工程了。接下來,只要獲取到  拉流 URL,就能實現 視頻直播功能。
本文針對ios端編譯流程安卓參考流程大體一樣,提出跨平台優化方案。
1.  github (https://www.githubs.cn/) 搜索查找 

 

 

 

 

2.克隆ijkplayer到桌面 
 cd Desktop/
 git clone https://github.com/Bilibili/ijkplayer.git ijkplayer

或者直接下載zip.解壓,切到解壓的文件夾內

 

(請忽略背景😂,年輕時候弄得電腦。)

 

打開 IJKMediaDemo,並編譯

提示: 'libavformat/avformat.h' file not found

 
查看  ijkplayer 的 README.md。
原因libavformat 是  ffmpeg 框架中的庫,而  ijkplayer 又是基於  ffmpeg 框架的,因此需要編譯  ffmpeg

3.下載ffmpeg

 cd ijkplayer

git checkout -B latest k0.8.8 ./init-ios.sh (下載ffmpeg)

注:下載最好使用FQ軟件,本人使用藍燈設置全局代理。下載很快,否則容易失敗。

要下載一會,下載完成之后,在ios目錄下就有了ffmpeg文件:

這時候我們的 ffmpeg 就下載好了,再次運行 IJKMediaDemo

發現還是報上面的錯誤,因為執行init-ios.sh,只是下載ffmpeg源碼,但是源碼並沒有參與編譯,需要把源碼編譯成.a文件:

4、編譯 ffmpeg 庫

進入 ios 文件的目錄中

cd ios 
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all

注:1.執行 ./compile-ffmpeg.sh clean ,目的是刪除一些文件和文件夾,為編譯ffmpeg.sh做准備,在編譯ffmpeg.sh的時候,會自動創建剛剛

刪除的那些文件,為避免文件名沖突,因此在編譯ffmpeg.sh之前先刪除等會會自動創建的文件夾或者文件

      2.執行 ./compile-ffmpeg.sh all 目的是編譯各個平台的ffmpeg庫,並生成所以平台的通用庫。      

可能遇到的問題:

warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7' [-Wignored-optimization-argument]

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....

 不支持arm7

 那么刪除這個編譯目標

 解決辦法:

打開ios目錄下這個 compile-ffmpeg.sh  文件

第24行 改為: FF_ALL_ARCHS_IOS8_SDK="arm64 i386 x86_64"

第120行 改為: if [ "$FF_TARGET" = "armv7s" -o "$FF_TARGET" = "arm64" ]; then

第159行 改為: echo " compile-ffmpeg.sh arm64|i386|x86_64"

其問題參考  https://www.jianshu.com/p/8668b38a629e

5.這時候編譯成功已經可以運行列子了

如需打包framework參考:文章三

ijkplayer - 拓展:

6.優化加速

延遲優化

發現拉流存在3-6秒延遲,這個根據七牛直播雲大牛講解的一些問題點。進行優化。 

丟包處理方案參考

a),有音頻流和視頻流,或者只有音頻流情況下,當audioq達到一定的duration,就丟掉前面一部分數據包,因為默認是AV_SYNC_AUDIO_MASTER,視頻會追上來。
b),只有視頻流情況,當videoq達到一定的duration,就丟掉前面一部分數據包。

 

開始本人修改丟失幀數過大,雖然延遲不存在了,但是同時測試局域網出現供不應求現象,就是畫面過一混會卡頓。因此還是修改緩存時間比較好。

ff_ffplay.c read_thread 線程中,在每次 av_read_frame后去判斷緩存隊列有沒有達到最大時長。這里需要把原來的realtime設置為0。

別的不說直接上代碼

通過修改源文件,因為ijkplayer實際上是基於ffplay.c實現的: 
ijkmedia>ijkplayer>ff_ffplay.c這個文件

 

static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) {
    if(vp->serial == nextvp->serial) {
        doubleduration = nextvp->pts - vp->pts;
    if(isnan(duration) || duration <=0|| duration > is->max_frame_duration)
        return vp->duration;
      else
       return duration;
   }else{
    return 0.0;
  }
}

改成直接返回duration

static double vp_duration(VideoState*is,Frame*vp,Frame*nextvp) {
     return vp->duration;
}

接着改staticintffplay_video_thread這個方法:

static int ffplay_video_thread(void*arg){
    FFPlayer*ffp = arg;
    VideoState*is = ffp->is;
    AVFrame*frame =av_frame_alloc();
    doublepts;
    doubleduration;
    intret;
    AVRationaltb = is->video_st->time_base;
    //注釋如下一行代碼
    //AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL);

    //......省略部分代碼

    //注釋如下一行代碼
    //duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational)  {frame_rate.den, frame_rate.num}) : 0);
    //直接這里寫出
    duration=0.01;

   //........
}

延遲明顯降低,高分辨率開啟硬解碼,不支持的話會自動切換到軟解,就算開啟mediacodec,如果設備不支持,顯示的解碼器也是avcodec軟解

參數配合設置如下(由於c碼,安卓蘋果參數基本一樣)

修改后基本延遲很低了1秒左右。然后

直接上修改后的代碼參數配合編譯的包

    
  //播放前的探測Size,默認是1M, 改小一點會出畫面更快
  [options setFormatOptionIntValue:1024 * 16 forKey:@"probesize"];
  //播放前的探測時間
  [options setFormatOptionIntValue:50000 forKey:@"analyzeduration"];
  //默認好像是硬解開啟軟解
  [options setPlayerOptionIntValue:0 forKey:@"videotoolbox"];
  //解碼參數,畫面更清晰
  [options setCodecOptionIntValue:IJK_AVDISCARD_DEFAULT forKey:@"skip_loop_filter"];
  //這個目前理解應該是丟幀數設置
  [options setCodecOptionIntValue:IJK_AVDISCARD_DEFAULT forKey:@"skip_frame"];
  [options setPlayerOptionIntValue:3000 forKey:@"max_cached_duration"];   // 最大緩存大小是3秒,可以依據自己的需求修改
  [options setPlayerOptionIntValue:1 forKey:@"infbuf"];  // 無限讀
  [options setPlayerOptionIntValue:0 forKey:@"packet-buffering"];  //  關閉播放器緩沖
    

7.如此設置已經基本可以實現0延遲播放了。

集成到自己項目見:
ijkplayer - 拓展:之打包framwork

其他一些優化本人也做了一些嘗試。詳情見下篇。

ijkplayer的一些優化

安卓端本人根據參數翻譯代碼設置如下:

ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 1024 * 16);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", 50000);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_frame", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max_cached_duration", 3000);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "infbuf", 1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0);
  

 

另外如果是后台播放可以參考改變設置

// Param for playback
//ios
[options setPlayerOptionIntValue:0 forKey:@"max_cached_duration"]; [options setPlayerOptionIntValue:0 forKey:@"infbuf"]; [options setPlayerOptionIntValue:1 forKey:@"packet-buffering"];
//android
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max_cached_duration", 0); ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "infbuf", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 1);
 
         

另外一些其他參數參考定義如下,跟據需要修改。

//開啟硬件解碼
[options setPlayerOptionIntValue:1 forKey:@"videotoolbox"];

// 設置音量大小,256為標准音量。(要設置成兩倍音量時則輸入512,依此類推)
[options setPlayerOptionIntValue:512 forKey:@"vol"];

// 最大fps
[options setPlayerOptionIntValue:30 forKey:@"max-fps"];

// 跳幀開關,如果cpu解碼能力不足,可以設置成5,否則
// 會引起音視頻不同步,也可以通過設置它來跳幀達到倍速播放
[options setPlayerOptionIntValue:0 forKey:@"framedrop"];

// 指定最大寬度,我沒試過
[options setPlayerOptionIntValue:960 forKey:@"videotoolbox-max-frame-width"];

// 自動轉屏開關,我沒試過
[options setFormatOptionIntValue:0 forKey:@"auto_convert"];

// 重連次數, 我沒試過
[options setFormatOptionIntValue:1 forKey:@"reconnect"];

// 超時時間,timeout參數只對http設置有效,若果你用rtmp設置timeout,ijkplayer內部會忽略timeout參數。rtmp的timeout參數含義和http的不一樣。
[options setFormatOptionIntValue:30 * 1000 * 1000 forKey:@"timeout"];

// 幀速率(fps)  我沒試過(可以改,確認非標准楨率會導致音畫不同步,所以只能設定為15或者29.97)
[options setPlayerOptionIntValue:29.97 forKey:@"r"];

Note: 這里有個比較有用的參數,skip_loop_filter

// for codec option 'skip_loop_filter' and 'skip_frame'
typedef enum IJKAVDiscard {
    /* We leave some space between them for extensions (drop some
     * keyframes for intra-only or drop just some bidir frames). */
    IJK_AVDISCARD_NONE    =-16, ///< discard nothing
    IJK_AVDISCARD_DEFAULT =  0, ///< discard useless packets like 0 size packets in avi
    IJK_AVDISCARD_NONREF  =  8, ///< discard all non reference
    IJK_AVDISCARD_BIDIR   = 16, ///< discard all bidirectional frames
    IJK_AVDISCARD_NONKEY  = 32, ///< discard all frames except keyframes
    IJK_AVDISCARD_ALL     = 48, ///< discard all
} IJKAVDiscard;

前面兩個都看得懂
第三個是拋棄非參考幀(I幀)
第四個是拋棄B幀
第五個是拋棄除關鍵幀以外的,比如B,P幀
第六個是拋棄所有的幀,這我就奇怪了,之前Android默認的就是48,難道把所有幀都丟了?
那就沒有視頻幀了, 所以應該不是這么理解,
應該是skip_loop_filter和skip_frame的對象要過濾哪些幀類型。

skip_loop_filter這個是解碼的一個參數,叫環路濾波,
設置成48和0,圖像清晰度對比,0比48清楚,理解起來就是,
0是開啟了環路濾波,過濾的是大部分,
而48基本沒啟用環路濾波,所以清晰度更低,但是解碼性能開銷小

skip_loop_filter(環路濾波)簡言之:
a:環路濾波器可以保證不同水平的圖像質量。
b:環路濾波器更能增加視頻流的主客觀質量,同時降低解碼器的復雜度。
具體參考:
http://blog.csdn.net/h514434485/article/details/52241778 http://www.cnblogs.com/TaigaCon/p/5500110.html skip_frame我沒完全理解意思,應該是等同上面這個類似。

另外安卓參數基本一樣
接口不同而已,注意屬性的分類
eg:OPT_CATEGORY_PLAYER
//可以打開h265硬解;
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-hevc", 1);

//開啟mediacodec硬解
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 1);
 


 下篇

ijkplayer的一些優化

 

參考前人經驗更新

輪子使用中

1、https://blog.csdn.net/ssy_1992/article/details/79191727    //編譯流程

或 https://www.jianshu.com/p/9a69af13835e 

注意FQ下載編譯。

2、優化

https://mp.weixin.qq.com/s?__biz=MjM5NzAwNDI4Mg==&mid=2652193023&idx=1&sn=d01045267be48621ac93c145af46cd53&chksm=bd01766a8a76ff7cd9e1e1994f5db2dab53560c44579b3bfef14a32bf638245b28de1405b026&scene=21#wechat_redirect

 


 

 

覺得有用的同學點個關注,或者留言評論區,看到郵件提示消息盡快回復。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM