iOS基於FFmpeg之配置FFmpeg架構(二)

來源:互聯網
上載者:User

標籤:

本文出自:這裡摘自http://blog.sina.com.cn/s/blog_47522f7f0102vbwp.html,按步驟實踐可行。感謝!

1. FFMPEG階層的簡單理解

要使用FFMPEG,首先需要理解FFMPEG的代碼結構。根據志哥的提示,ffmpeg的代碼是包括兩部分的,一部分是library,一部分是tool。api都是在library裡面,如果直接調api來操作視頻的話,就需要寫c或者c++了。另一部分是tool,使用的是命令列,則不需要自己去編碼來實現視頻操作的流程。實際上tool只不過把命令列轉換為api的操作而已。

2. 預熱-在mac os下使用ffmpeg

在mac os下使用ffmpeg比較簡單,可以直接使用命令列來操作。首先安裝ffmpeg,這裡預設系統已經安裝好brew,只需要在終端上輸入:

brew install ffmpeg

等待安裝結束即可。

安裝結束後,嘗試以下命令:

ffmpeg -i input.mp4 output.avi

如果能順利轉換,表明安裝成功

3. 編譯能在iOS下使用的FFMPEG library庫

這一步是編譯1所說的library,編譯好之後可以調用FFMPEG的api。網上有一些方法,但都要自己手動編譯,稍顯複雜而且比較陳舊。按照app store的需求,編譯出來的包還必須支援arm64。我在萬能的github中找到一個能夠"一鍵編譯"的指令碼,地址如下:

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

而且寫這個指令碼的歪果仁挺好人,更新很及時,已經更新到了最新的2.5.3版本。下載下來,只有一個build-ffmpeg.sh指令檔。在終端中轉至指令碼的目錄,執行命令:

./build-ffmpeg.sh

指令碼則會自動從github中把ffmpeg源碼下到本地並開始編譯。

編譯結束後,檔案目錄如下:

【iOS開發】iOS下使用FFMPEG的一些總結

其中,ffmpeg-2.5.3是源碼,FFmpeg-iOS是編譯出來的庫,裡面有我們需要的.a靜態庫,一共有7個。

執行命令:

lipo -info libavcodec.a

查看.a包支援的架構,這幾個包都支援了armv7 armv7s i386 x86_64 arm64這幾個架構,這個指令碼果真是業界良心啊~~~

4.在xcode中引入FFMPEG library庫

建立工程,把上面編譯好的FFmpeg-iOS拖到xcode工程中,添加一個標頭檔引用

 

#include "avformat.h"

添加一個api語句:

av_register_all();

添加一個空的類,把執行檔案.m尾碼改為.mm,開啟混編模式。

添加相應的framework,包括avfoundation和coremedia。

運行工程,如果沒有報錯,則表明編譯成功。

 

5.在xcode項目中使用命令列

執行到第4步,已經可以使用library庫了。但是如果要對視頻進行操作,還是需要手動寫很多代碼去調用api,工作量較大,自然不如直接寫命令列方便。為了命令列能夠在xcode工程中使用,還需要做以下工作:

(1)添加源碼中的tools,具體檔案包括:

【iOS開發】iOS下使用FFMPEG的一些總結

(2)添加Header Search Paths

在target--build setting中搜尋Header Search Paths,並在Header Search Paths下面添加源碼ffmpeg-2.5.3和scratch的路徑。

(3)修改ffmpeg.h和ffmpeg.c源碼

如果此時run這個工程,則會報錯,原因是工程裡面有2個main函數,此時處理方法為:

在ffmpeg.h中添加一個函式宣告:

int ffmpeg_main(int argc, char **argv);

在ffmpeg.c中找到main函數,把main函數改為ffmpeg_main。

(4)調用命令列範例

添加標頭檔:#import "ffmpeg.h"

調用命令列

int numberOfArgs = 16;

char** arguments = calloc(numberOfArgs, sizeof(char*));

arguments[0] = "ffmpeg";

arguments[1] = "-i";

arguments[2] = inputPath;

arguments[3] = "-ss";

arguments[4] = "0";

arguments[5] = "-t";

arguments[6] = durationChar;

arguments[7] = "-vcodec";

arguments[8] = "copy";

arguments[9] = "-acodec";

arguments[10] = "aac";

arguments[11] = "-strict";

arguments[12] = "-2";

arguments[13] = "-b:a";

arguments[14] = "32k";

arguments[15] = outputPath;

int result = ffmpeg_main(numberOfArgs, arguments);

其中inputpath和outputpath是檔案路徑。經測試,這兩個路徑不支援asset-library://協議和file:// 協議,所以如果是要用相簿的檔案,我目前的解決辦法是把它拷貝到沙箱裡面。

6. 改關閉進程為關閉線程

如果順利進行到了第5步,在app中是能夠用命令列處理視頻了,但會出現一個問題,app會退出。經肖大神提醒,發現了命令列執行完畢之後會退出進程。而iOS下只能啟動一個進程,因此必須改關閉進程為關閉線程,或者直接把關閉進程的方法給注掉。

在ffmpeg.c中可以看到,執行退出進程的方法是exit_program,定位到了cmdutils.c中執行了c語言的exit方法。這裡我將它改為了pthread_exit(需要添加#include 標頭檔)。在xcode項目中使用時,則可以用NSThread來新開一個線程,執行完畢之後,把線程關閉了即可。再使用NSThreadWillExitNotification通知,即可監聽線程退出的情況。

7. 修複ffmpeg.c裡面的一個bug

在實際項目中,可能需要多次調用命令列,但在多次調用命令列的過程中,發現ffmpeg.c的代碼中會訪問空屬性導致程式崩潰。逐步debug後發現,很多指標已經置空了,但它們的計數卻沒有置零,不知道是不是ffmpeg.c的一個bug。修複方法如下:在ffmpeg_cleanup方法下,將各個計數器置零,包括:

nb_filtergraphs

nb_output_files

nb_output_streams

nb_input_files

nb_input_streams

置零之後,重複使用ffmpeg_main方法一切正常。

iOS基於FFmpeg之配置FFmpeg架構(二)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.