1. 程式人生 > >FFmpeg在Android上的移植優化步驟

FFmpeg在Android上的移植優化步驟

從事多媒體軟體開發的人幾乎沒有不知道FFmpeg的,很多視訊播放器都是基於FFmpeg開發的。如今最火的智慧手機作業系統Android上的很多第三方視訊播放器也是基於FFmpeg實現全格式支援。由於Android通常跑在ARM處理器上,而且Android使用了自己的libc庫(即bionic),因此要在Android上編譯和使用FFmpeg需要做一些移植工作,好在FFmpeg本身用C寫成,很好地支援跨平臺移植,實現這個目的並不難,事實上已經有很多前輩做過這方面的工作並公開了他們的成果。

1.     Rockplayer:

2.     havlenapetr:

3.     halfninja:

4.     olvaffe's:

5.     流媒體開發論壇 - 羅索工作室:

當下本人也做這方面的事情,主要是優化ffmpeg編解碼的效能,當然首先就是要搭建環境,編譯程式碼,測試程式碼效能,然後優化模組,編譯測試和除錯,最終再測試效能:看了很多文章,對於一些新手是有點幫助,但是都不是很全面,下面簡單記錄下我如何搭建環境,如何編譯,測試: 

可以使用Rockplayer的方案進行實踐。Rockplayer是Android上最有名的第三方視訊播放器之一,其開發者根據LGPL協議公開了所使用的FFmpeg原始碼,該方案用Android NDK將FFmpeg原始碼編譯生成一個單獨的共享庫libffmpeg.so,其中靜態連結了libavformat、libavcodec、libavutil等模組,要使用FFmpeg只需要呼叫這一個.so即可。當然有了這個庫還只是第一步,要利用FFmpeg開發一個自己的播放器或者把FFmpeg整合到Android本身的播放引擎stagefright中還需要很多其他工作,包括針對硬體平臺進行優化。目前我做的只是編譯出libffmpeg.so以及將FFmpeg自帶的工具ffmpeg在adb shell中跑起來。我是在Android 3.2(Honeycomb)上編譯FFmpeg,所用NDK版本為r7,在Android的其他版本上編譯也大同小異。

題外話:Rockplayer之前也和他們談過合作的事情,一家幾個人搞得小型公司(其實也談不上公司了),office在上海張江一個不起眼的小區裡,也不能說他們沒有技術含量,只能說他們找到一個突破口,能掙點小錢,他們的android手機播放器設計原則是支援要全,畫質要清晰,效能不是主要,面向中高檔手機,配置相對來說就高些。

下面把具體編譯步驟描述如下,假定NDK安裝在~/android-ndk-r7:

1.   首先從FFmpeg官網下載最新的release版本原始碼ffmpeg-0.11.tar.gz解壓縮到Android原始碼樹的ffmpeg/下。

  準備一個編譯指令碼build_android.sh並放在ffmpeg/下面,這個指令碼也是Rockplayer提供的,需做一些修改,其內容附在後面。我目前用的也會附在後面。

  在ffmpeg目錄下執行./build_android.sh開始編譯FFmpeg,編譯好的libffmpeg.so會放在資料夾android裡面,一共有3個版本分別對應3種ARM體系結構,包括armv7-a、armv7-a-vfp、armv6_vfp,根據所執行的硬體平臺選取其中一個版本。為了編譯使用FFmpeg的程式時可以方便地找到libffmpeg.so,可將它複製到$OUT/system/lib/和$OUT/obj/lib/,當然這一步也可以加在build_android.sh中做。

4.   接下來就是編譯可執行檔案ffmpeg了,這個工具可以在命令列下完成FFmpeg提供的幾乎所有功能包括編碼、解碼、轉碼等,也是用來除錯和驗證很有用的工具。其實上述編譯完後在$ANDROID_BUILD_TOP/external/ffmpeg/下也會生成ffmpeg,但是在裝置上無法執行。為了編出能在裝置上執行的ffmpeg,可以寫一個簡單的Android.mk,其內容如下:

[cpp] view plaincopyprint?
  1. LOCAL_PATH:= $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES:= \  
  4.        cmdutils.c \  
  5.        ffmpeg.c  
  6. LOCAL_C_INCLUDES :=  
  7. LOCAL_SHARED_LIBRARIES := \  
  8.        libffmpeg  
  9. LOCAL_PRELINK_MODULE := false
  10. LOCAL_MODULE := ffmpeg  
  11. include $(BUILD_EXECUTABLE)  

也可以在E:\android-ndk-r7-windows\android-ndk-r7\samples\test-libstdc++\jni這個目錄修改下Android.mk, 修改為:

[cpp] view plaincopyprint?
  1. LOCAL_PATH:= $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES := ffmpeg.c cmdutils.c  
  4. #LOCAL_PREBUILT_LIBS := libffmpeg
  5. LOCAL_ARM_MODE := arm  
  6. LOCAL_C_INCLUDES += \  
  7.     $(LOCAL_PATH)/include  \  
  8.     $(LOCAL_PATH)/include/libavcodec \  
  9.     $(LOCAL_PATH)/ \  
  10.     $(LOCAL_PATH)/include/libavfilter \  
  11.     $(LOCAL_PATH)/include/libavdevice \  
  12.     $(LOCAL_PATH)/include/libavutil  
  13. #LOCAL_LDLIBS := -L$(LOCAL_PATH) -lffmpeg
  14. LOCAL_LDLIBS := libffmpeg.so  
  15. LOCAL_MODULE := ffmpeg  
  16. include $(BUILD_EXECUTABLE)  


當然要把ffmpeg.c cmdutils.c和libffmpeg.so拷貝到當前目錄。

5.   將上面編好的libffmpeg.so和ffmpeg分別用adb push複製到裝置的/system/lib/和/system/bin/,push之前可先對libffmpeg.so做一下strip否則太大。現在就可以在adb shell中執行ffmpeg了,使用方法與在PC上相同。當然如果要用到其他開源庫例如x264那麼還需要把它們也移植到Android。

以上是基本的步驟,僅供參考,可以根據具體情況修改build_android.sh裡面的配置選項。如前所述,編譯FFmpeg只是第一步,後續還有很多工作需要做,今後如果有進展再貼上來。

最後附上build_android.sh供參考,在此也感謝Rockplayer的開發者:

[cpp] view plaincopyprint?
  1. #!/bin/bash
  2. ######################################################
  3. # FFmpeg builds script for Android+ARM platform
  4. #
  5. # This script is released under term of
  6. #   CDDL (http://www.opensource.org/licenses/cddl1)
  7. # Wrote by pinxue ([email protected]) from RockPlayer.com
  8. #                                   2010-8 ~ 2011-4
  9. ######################################################
  10. ######################################################
  11. # Usage:
  12. #   put this script in top of FFmpeg source tree
  13. #   ./build_android
  14. #
  15. # It generates binary for following architectures:
  16. #     ARMv6
  17. #     ARMv6+VFP
  18. #     ARMv7+VFPv3-d16 (Tegra2)
  19. #     ARMv7+Neon (Cortex-A8)
  20. #
  21. # Customizing:
  22. # 1. Feel free to change ./configure parameters for more features
  23. # 2. To adapt other ARM variants
  24. #       set $CPU and $OPTIMIZE_CFLAGS
  25. #       call build_one
  26. ######################################################
  27. NDK=~/android-ndk-r7  
  28. PLATFORM=$NDK/platforms/android-8/arch-arm/  
  29. PREBUILT=../../prebuilt/linux-x86/toolchain/arm-eabi-4.4.3  
  30. function build_one  
  31. {  
  32. # -fasm : required. Android header file uses asm keyword instead of __asm__ , but most of c dialect (like ansi,c99,gnu99) implies -fno-asm.
  33. #   ~/android/android-ndk-r4/build/platforms/android-5/arch-arm//usr/include/asm/byteorder.h: In function '___arch__swab32':
  34. #   ~/android/android-ndk-r4/build/platforms/android-5/arch-arm//usr/include/asm/byteorder.h:25: error: expected ')' before ':' token
  35. # -fno-short-enums : optimized.  Else FFmpeg obj will generate a huge number of warning for variable-size enums,
  36. #   though we may suppress them by --no-enum-size-warning, it would be better to avoid it.
  37. #   .../ld: warning: cmdutils.o uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail
  38. # --extra-libs="-lgcc" : required. Else cannot solve some runtime function symbols
  39. #   ... undefined reference to `__aeabi_f2uiz'
  40. # --enable-protocols : required. Without this option, the file open always fails mysteriously.
  41. #   FFmpeg's av_open_input_file will invoke file format probing functions, but because most of useful demuxers has flag of zero
  42. #   which cause them are ignored during file format probling and fall to url stream parsing,
  43. #   if protocols are disabled, the file:// url cannot be opened as well.
  44. # $PREBUILT/bin/arm-eabi-ar d libavcodec/libavcodec.a inverse.o : required.
  45. #   FFmpeg includes two copies of inverse.c both in libavutil and libavcodec for performance consideration (not sure the benifit yet)
  46. #   Without this step, final ld of generating libffmpeg.so will fail silently, if invoke ld through gcc, gcc will collect more reasonable error message.
  47. # -llog: debug only, FFmpeg itself doesn't require it at all.
  48. #   With this option, we may simply includes "utils/Log.h" and use LOGx() to observe FFmpeg's behavior
  49. #   PS, it seems the toolchain implies -DNDEBUG somewhere, it would be safer to use following syntax
  50. #    #ifdef NDEBUG
  51. #        #undef NDEBUG
  52. #        #define HAVE_NDEBUG
  53. #    #endif
  54. #    #include "utils/Log.h"
  55. #    #ifdef HAVE_NDEBUG
  56. #        #define NDEBUG
  57. #        #undef HAVE_NDEBUG
  58. #    #endif
  59. # --whole-archive : required. Else ld generate a small .so file (about 15k)
  60. # --no-stdlib : required. Android doesn't use standard c runtime but invited its own wheal (bionic libc) because of license consideration.
  61. # space before \ of configure lines: required for some options. Else next line will be merged into previous lines's content and cause problem.
  62. #   Especially the --extra-cflags, the next line will pass to gcc in this case and configure will say gcc cannot create executable.
  63. # many options mentioned by articles over internet are implied by -O2 or -O3 already, need not repeat at all.
  64. # two or three common optimization cflags are omitted because not sure about the trade off yet. invoke NDK build system with V=1 to find them.
  65. # -Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x mentioned by almost every articles over internet, but it is not required to specify at all.
  66. # -Dipv6mr_interface=ipv6mr_ifindex : required. Android inet header doesn't use ipv6mr_interface which is required by rfc, seems it generate this user space header file directly from kernel header file, but Linux kernel has decided to keep its own name for ever and ask user space header to use rfc name.
  67. # HAVE_SYS_UIO_H : required. Else:
  68. # In file included from ~/android/android-ndk-r4/build/platforms/android-5/arch-arm//usr/include/linux/socket.h:29,
  69. #                 from ~/android/android-ndk-r4/build/platforms/android-5/arch-arm//usr/include/sys/socket.h:33,
  70. #                 from libavformat/network.h:35,
  71. #                 from libavformat/utils.c:46:
  72. #~/android/android-ndk-r4/build/platforms/android-5/arch-arm//usr/include/linux/uio.h:19: error: redefinition of 'struct iovec'
  73. #
  74. # --disable-doc : required because of strange bug of toolchain.
  75. ./configure --target-os=linux \  
  76. 相關推薦

    FFmpeg在Android移植優化步驟

    從事多媒體軟體開發的人幾乎沒有不知道FFmpeg的,很多視訊播放器都是基於FFmpeg開發的。如今最火的智慧手機作業系統Android上的很多第三方視訊播放器也是基於FFmpeg實現全格式支援。由於Android通常跑在ARM處理器上,而且Android使用了自己的l

    MySql的優化步驟

    where pri 子句 刪除索引 tex 提高 myisam 信息 更新 MySql優化的一般步驟: 1.通過show status 命令了解各種sql的執行效率   SHOW STATUS提供msyql服務器的狀態信息   一般情況下,我們只需要了解以”Com”開頭的指

    Linux安裝JDK步驟

    連接 安裝文件 profile 註意 參考 內容 root lib .gz 之前只是在Windows上安裝過JDK,現在公司需要在Linux上安裝java環境,這裏總結下安裝的過程 1、下載JDK 下載地址:http://www.oracle.com/technetwork

    【轉】stm32CubeMx移植自己的printf()和scanf()函數

    smi config 用戶 type 連接器 標準庫 can 修改 esp 要想printf()和scanf() 函數工作,我們需要把printf()和scanf() 重新定向到串口中。重定向是指用戶可以自己重寫C 的庫函數,當連接器檢查到用戶編寫了與C 庫函數相同名字的函

    嵌入式Linux移植unzip工具

    16px 文件 bsp ont div 嵌入 for .gz .tar.gz   由於busybox編譯出來的unzip不支持有密碼的壓縮包解壓,因此基於unzip60源碼包,交叉編譯一個嵌入式Linux上的unzip工具。 1.下載地址是: http://sourcefo

    Zabbix 3.4 在CentOS 7.2 安裝詳細步驟

    ade cati wall ide end The systemd processes image 一、環境準備操作系統: [root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.3.1611

    代碼性能優化步驟

    .so ket 一個 常量 邏輯 日誌 earch arch 使用 0、首先測試一個當前性能指標 1、代碼規範 (符合阿裏開發手冊規範,日誌self4j,常量,線程池等) 2、使用性能更好的工具類 (例如排序使用treeSet,而不是使用collections.sort()

    關於PyQt5,在pycharm的安裝步驟

    綠色 pyqt5 發現 sta ins 窗口 好的 輸入 http 前序 之前學習了一款GUI圖形界面設計的Tkinter庫,但是經大佬的介紹,PyQT5全宇宙最強,一臉的苦笑 毫不猶豫的選擇轉戰PyQT5,在學習之前需要先安裝一些必須程序,在一番查閱後,發現PyQt5的學

    springMVC3學習(十二)--檔案優化CommonsMultipartResolver

    基於上一篇檔案上傳發現效率很慢,我們應該對它進行優化  使用springMVC對檔案上傳的解析器 來處理檔案上傳的時候需要在spring的applicationContext裡面加上springMVC提供的MultipartResolver的申明 這樣客戶端請求的時候 spr

    MySQL之SQL語句優化步驟

    MySQL查詢擷取分析步驟: 一、開啟慢查詢日誌,捕獲慢SQL 二、explain+慢SQL分析 三、show profile查詢SQL語句在伺服器中的執行細節和生命週期 四、SQL資料庫伺服器引數調優 一、開啟慢查詢日誌,捕獲慢SQL 1、檢視慢查詢日誌是否開啟 SHO

    HTTP2.0,HTTP1.1,HTTP1.0三者在通性效能優化方法

    本文從從通訊效能角度,來分析對比HTTP1.0和HTTP1.1之間的區別。以及HTTP1.1與HTTP2.0之間的區別。本文詳細內容組織如下 目錄 一丶HTTP1.0與HTTP1.1通訊效能上的區別 持久化連線 管線化技術 二丶HTTP2.0與HTTP1.1通訊效能上的區別 多路

    liunx安裝nodejs步驟

            第一步:首先下載node.js安裝包(這樣的方式比較好,比下載原始碼再編譯簡單)              

    springMVC3學習 十二 --檔案優化CommonsMultipartResolver

    分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

    java中的Executors簡介與多執行緒在網站逐步優化的運用案例

    提供Executor的工廠類 忽略了自定義的ThreadFactory、callable和unconfigurable相關的方法 newFixedxxx:在任意時刻,最多有nThreads個執行緒在處理task;如果所有執行緒都在執行時來了新的任務,它會被扔

    js程式碼優化

    例1  if ( config.url === '/web/teacher/classes'  || config.url === '/web/teacher/students || config.url === '/web/teacher/groups ) {&nbs

    檔案優化

    一、思路: (1)可移植性(利用properties檔案配置檔案儲存位置) (2)獲取檔案字尾名 (3)生成新的檔名(UUID) (4)單檔案儲存,並返回新的檔案的儲存地址(包括新的檔名) (5)多檔案儲存(List<檔案資訊類>) (3)儘量減少查詢

    MySQL索引優化步驟總結

    在專案使用mysql過程中,隨著系統的執行,發現一些慢查詢,在這裡總結一下mysql索引優化步驟 1.開發過程優化 開發過程中對業務表中查詢sql分析sql執行計劃(尤其是業務流水錶),主要是檢視sql執行計劃,對sql進行優化。 explain執行計劃關鍵屬性 select_type,possibl

    hikey970學習-012 hikey970移植影象去雨深度神經網路演算法

    摘要:本文在hikey970嵌入式裝置上執行影象去雨深度神經網路演算法,驗證hikey970執行神經網路模型的效能與效果。 一、影象去雨簡介     影象去雨處理指的是對於一張雨中的圖片,去除畫面中的雨滴,得到還原後的圖片,與圖片去霧、超解析度等同屬CV領域中影

    spring boot專案打包成war 並在tomcat執行的步驟詳解

    把spring-boot專案按照平常的web專案一樣釋出到tomcat容器下 一、修改打包形式 在pom.xml裡設定 <packaging>war</packaging> 二、移除嵌入式tomcat外掛 在pom.xml裡找到spri

    linux部署jenkins步驟小計

    一、部署jdk環境 1.下載jdk包,解壓,放在選定的位置,我本次jdk包放置在“/usr/local/java/jdk” 目錄下 2.配置環境變數    1)開啟/etc/profile檔案,在命令框中輸入命令:vi  /etc/profile