Android內置的編解碼器實在太少,於是我們需要FFmpeg。Android提供了NDK,為我們使用FFmpeg這種C語言代碼提供了方便。
不過為了用NDK編譯FFmpeg,還真的花費了不少時間,也得到了很多人的幫助,最應該謝謝havlenapetr。我覺得我現在這些方法算是比較簡潔的了--
下面就盡量詳細的說一下我是怎麼在項目中使用FFmpeg的,但是基於我混亂的表達能力,有不明白的就問我。
你得了解JNI和Android NDK的基本用法,若覺得我的文章還不錯,可以看之前寫的JNI簡單入門和Android NDK入門
首先創建一個標準的Android項目vPlayer
android create project -n vPlayer -t 8 -p vPlayer -k me.abitno.vplayer -a PlayerView
然後在vPlayer目錄里
mkdir jni && cd jni
wget http //ffmpeg org/releases/ffmpeg-0.6.tar.bz2
tar xf ffmpeg-0.6.tar.bz2 && mv ffmpeg-0.6 ffmpeg && cd ffmpeg
在ffmpeg下新建一個config.sh,內容如下,注意把PREBUILT和PLATFORM設置正確。另外裡面有些參數你也可以自行調整,我主要是為了配置一個播放器而這樣設置的。
#!/bin/bash
PREBUILT=/home/abitno/Android/android-ndk-r4/build/prebuilt/linux-x86/arm-eabi-4.4.0
PLATFORM=/home/abitno/Android/android-ndk-r4/build/platforms/android-8/arch-arm
./configure --target-os=linux \
--arch=arm \
--enable-version3 \
--enable-gpl \
--enable-nonfree \
--disable-stripping \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffserver \
--disable-ffprobe \
--disable-encoders \
--disable-muxers \
--disable-devices \
--disable-protocols \
--enable-protocol=file \
--enable-avfilter \
--disable-network \
--disable-mpegaudio-hp \
--disable-avdevice \
--enable-cross-compile \
--cc=$PREBUILT/bin/arm-eabi-gcc \
--cross-prefix=$PREBUILT/bin/arm-eabi- \
--nm=$PREBUILT/bin/arm-eabi-nm \
--extra-cflags="-fPIC -DANDROID" \
--disable-asm \
--enable-neon \
--enable-armv5te \
--extra-ldflags="-Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtbegin.o $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtend.o -lc -lm -ldl"
運行config.sh開始configure
chmod +x config.sh
./config.sh
configure完成後,編輯剛剛生成的config.h,找到這句
#define restrict restrict
Android的GCC不支持restrict關鍵字,於是修改成下面這樣
#define restrict
編輯libavutil/libm.h,把其中的static方法都刪除。
分別修改libavcodec、libavfilter、libavformat、libavutil、libpostproc和libswscale下的Makefile,把下面兩句刪除
include $(SUBDIR)../subdir.mak
include $(SUBDIR)../config.mak
在ffmpeg下添加一個文件av.mk,內容如下
# LOCAL_PATH is one of libavutil, libavcodec, libavformat, or libswscale
#include $(LOCAL_PATH)/../config-$(TARGET_ARCH).mak
include $(LOCAL_PATH)/../config.mak
OBJS :=
OBJS-yes :=
MMX-OBJS-yes :=
include $(LOCAL_PATH)/Makefile
# collect objects
OBJS-$(HAVE_MMX) += $(MMX-OBJS-yes)
OBJS += $(OBJS-yes)
FFNAME := lib$(NAME)
FFLIBS := $(foreach,NAME,$(FFLIBS),lib$(NAME))
FFCFLAGS = -DHAVE_AV_CONFIG_H -Wno-sign-compare -Wno-switch -Wno-pointer-sign
FFCFLAGS += -DTARGET_CONFIG=\"config-$(TARGET_ARCH).h\"
ALL_S_FILES := $(wildcard $(LOCAL_PATH)/$(TARGET_ARCH)/*.S)
ALL_S_FILES := $(addprefix $(TARGET_ARCH)/, $(notdir $(ALL_S_FILES)))
ifneq ($(ALL_S_FILES),)
ALL_S_OBJS := $(patsubst %.S,%.o,$(ALL_S_FILES))
C_OBJS := $(filter-out $(ALL_S_OBJS),$(OBJS))
S_OBJS := $(filter $(ALL_S_OBJS),$(OBJS))
else
C_OBJS := $(OBJS)
S_OBJS :=
endif
C_FILES := $(patsubst %.o,%.c,$(C_OBJS))
S_FILES := $(patsubst %.o,%.S,$(S_OBJS))
FFFILES := $(sort $(S_FILES)) $(sort $(C_FILES))
接下來要添加一系列的Android.mk,在jni根目錄下的內容如下
include $(all-subdir-makefiles)
在ffmpeg目錄下,Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale
LOCAL_MODULE := ffmpeg
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
libavformat/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_CFLAGS += -include "string.h" -Dipv6mr_interface=ipv6mr_ifindex
LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)
libavcodec/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)
libavfilter、libavutil、libpostproc和libswscale下的Android.mk內容如下
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)
最外層的jni/Android.mk和jni/ffmpeg/Android.mk我只是隨便這樣寫的,你應該根據自己的需求改寫。
最後運行ndk-build,經過漫長的等待就編譯完成了。至於具體怎麼應用可能以後會寫,我變得太懶了。。。
轉載,僅供參考,祝你愉快,滿意請採納。
❷ android studio ndk-build怎麼配置環境
在開始配置Android Studio NDK環境之前,請確保您已下載並安裝了Android NDK。下載完成後,需為您的項目設置NDK路徑。具體操作是在項目的local.properties文件中添加一行ndk.dir=路徑/ndk,其中「路徑」為您的NDK安裝路徑。
接著,需要在項目的build.gradle文件中進行相應修改。打開build.gradle文件,進入android節點,添加ndkVersion '版本號',其中「版本號」為您的NDK版本號。
接下來,創建一個名為jni的文件夾。在jni文件夾下,創建一個新的C/C++源文件。為了便於後續開發,可以創建一個測試類文件,如創建一個名為MainActivity的java類,該類中包含一個簡單的測試函數。
然後,創建一個對應的頭文件(.h文件)。在jni文件夾下,創建一個名為MainActivity.h的文件,其中定義測試函數的原型。緊接著,創建一個對應的實現文件(.cpp文件),在jni文件夾下,創建一個名為MainActivity.cpp的文件,其中實現測試函數的具體邏輯。
最後,進行測試。在MainActivity.java文件中,包含MainActivity.h頭文件,並實現測試函數的調用。然後,運行項目,檢查是否正確實現了C/C++代碼。
❸ Android 音視頻開發之自己動手編譯 FFmpeg
前言
ffmpeg是一款在音頻和視頻領域具有重要地位的開源軟體,對於Android開發者,編譯ffmpeg是深入音視頻領域的關鍵步驟。為了實現這一目標,建議在具有Linux環境的系統上進行,如Ubuntu、Mac,可通過雲伺服器或虛擬機實現。本次教程使用了ndk版本android-ndk-r16b和ffmpeg版本ffmpeg-3.3.9。需要提前配置好環境變數,將ffmpeg和ndk解壓到相應目錄,並在/etc/profile文件中設置ndk路徑。通過編輯此文件,將ndk路徑添加到末尾。保存後刷新系統環境,通過echo $NDK_PATH驗證配置是否成功。
2. 編寫ffmpeg配置腳本
為了針對性地選擇編譯,可以創建一個ffmpeg_build.sh腳本來簡化流程。腳本需根據具體需求進行配置,以確保僅編譯所需功能。
3. 修改configure文件
在configure文件中,通過搜索特定代碼段,並進行相應的修改,以滿足特定需求。確保在修改後,安裝gcc和yasm。完成後,執行相關命令進行編譯。
4. 執行編譯腳本
經過上述步驟,ffmpeg編譯過程完成。成功後,將看到生成的android目錄和相關so庫文件。將這些so庫和include文件引入項目,即可進行音視頻開發。
5. 後話
在編譯ffmpeg過程中,可能會遇到各種問題,需要仔細檢查代碼和環境配置。對於Linux基礎不熟練的開發者,建議先行學習相關知識。如有疑問,歡迎在下方評論區提問,後續將推出更多與ffmpeg相關的音視頻處理教程,敬請期待。