FFmpeg:Android
안드로이드에서 FFmpeg를 사용하는 방법에 대한 설명.
FFmpeg 라이선스에 대하여
- LGPL 라이센스를 사용하는 AndEngine을 사용할시 jar 형태로 라이브러리를 사용하여 게임을 제작한다면 이것의 공개의무는?
- 제가 게임은 어떻게 개발하는지 모르겠는데 얼마전 대형사 프로젝트를 할때는 라이브러리와 함께 copyright 가 담긴 readme 파일을 라이브러리와 같은 폴더에 놓고 apk로 만들어 올렸습니다. 만약 문제가 생기면 저의 경우는 jni인터페이스 소스만 공개를 하면 되기 때문에 상관이 없다더군요. 근데 왠만하면 좀 큰기업이 아닌 이상은 안건드린다고 들었는데.
- GPL 보다는 약한 걸로 알고 있는데, 검색해보시면, 소스 비공개가 만만치를 않아서... GPL 이든 LGPL 이든 앤간하면 가져다 쓰지 않았던 걸로 기억합니다. 물론, 이쪽 정신에 맞게 소스를 공개해도 상관없다고 생각하신다면, 그냥 가져다 쓰셔도 무방하긴 합니다.
Windows에서 Cygwin 사용시 make-standalone-toolchain.sh 사용방법
Cygwin을 사용하여 안드로이드 NDK에서 툴체인 추출한다. 사용한 NDK 버전은 r8e-x64 이다. (만약, NDK가 x64일 경우 --system=windows-x86_64
옵션을 추가해야 한다.)
cwlee@cwlee-zeki-pc /
$ /cygdrive/d/libs/android-ndk-r8e-x64/build/tools/make-standalone-toolchain.sh --platform=android-8 --install-dir=/cygdrive/d/proj/android-8-toolchains/
참고로, Cygwin에서 permission denied 와 관련된 문제가 발생될 경우, 관리자 권한으로 Cygwin을 실행하면 된다.
build_ffmpeg-android-arm.sh
Ubuntu에서 정상적으로 컴파일되는 스크립트 정보는 아래와 같다. (javacv-0.5-cppjars.zip 참조) (테스트환경: Ubuntu 12.04 LTS, FFmpeg 1.2.2)
ANDROID_BIN=$ANDROID_NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/
ANDROID_ROOT=$ANDROID_NDK/platforms/android-9/arch-arm/
tar -xjvf ffmpeg-$FFMPEG_VERSION.tar.bz2
mv ffmpeg-$FFMPEG_VERSION ffmpeg-$FFMPEG_VERSION-android-arm
cd ffmpeg-$FFMPEG_VERSION-android-arm
tar -xjvf ../last_stable_x264.tar.bz2
X264=`echo x264-snapshot-*`
cd $X264
./configure --enable-static --enable-pic --disable-cli --cross-prefix=$ANDROID_BIN/arm-linux-androideabi- --sysroot=$ANDROID_ROOT --host=arm-linux --extra-cflags="-DANDROID -fPIC -ffunction-sections -funwind-tables -fstack-protector -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -mfpu=neon -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit=300" --extra-ldflags="-nostdlib -Wl,--fix-cortex-a8 -lgcc -ldl -lz -lm -lc"
make -j4
cd ../
patch -p1 < ../ffmpeg-$FFMPEG_VERSION-android-arm.patch
./configure --prefix=$HOME/android --enable-shared --enable-gpl --enable-version3 --enable-runtime-cpudetect --disable-outdev=sdl --enable-libx264 --extra-cflags="-I$X264" --extra-ldflags="-L$X264" --enable-cross-compile --cc=$ANDROID_BIN/arm-linux-androideabi-gcc --sysroot=$ANDROID_ROOT --target-os=linux --arch=arm --extra-cflags="-DANDROID -fPIC -ffunction-sections -funwind-tables -fstack-protector -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -mfpu=neon -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit=300" --extra-ldflags="-nostdlib -Wl,--fix-cortex-a8" --extra-libs="-lgcc -ldl -lz -lm -lc" --disable-stripping --disable-symver --disable-programs
make -j4
LIBS="libavcodec/libavcodec.so libavdevice/libavdevice.so libavfilter/libavfilter.so libavformat/libavformat.so libavutil/libavutil.so libpostproc/libpostproc.so libswresample/libswresample.so libswscale/libswscale.so"
$ANDROID_NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-strip $LIBS
mkdir -p com/googlecode/javacv/cpp/android-arm/
cp $LIBS com/googlecode/javacv/cpp/android-arm/
jar cvf ../ffmpeg-$FFMPEG_VERSION-android-arm.jar com/
rm -Rf com/
cd ../
만약, 컴파일중 라이브러리(so)에 새로운 파일(*.c
, *.h
)을 추가하고 싶다면 특정 라이브러리 디렉터리에 있는 Makefile을 다시 확인해보자.
-
NAME
: 적용하고싶은 라이브러리 파일이름. -
HEADERS
: 추가하고 싶은 헤더(*.h
)파일 목록. -
OBJS
: 라이브러리에 적용할 오브젝트(*.o
)파일.
이후, 컴파일된 so파일을 NDK에 연동하기 위하여 Android.mk를 아래와 같이 적용하면 된다.
LOCAL_PATH := $(call my-dir)
# include $(CLEAR_VARS)
# LOCAL_MODULE := ffmpeg
# LOCAL_SRC_FILES := libffmpeg.so
# LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg
# include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avcodec
LOCAL_SRC_FILES := libs/libavcodec.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avdevice
LOCAL_SRC_FILES := libs/libavdevice.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avfilter
LOCAL_SRC_FILES := libs/libavfilter.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avformat
LOCAL_SRC_FILES := libs/libavformat.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avutil
LOCAL_SRC_FILES := libs/libavutil.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := postproc
LOCAL_SRC_FILES := libs/libpostproc.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := swresample
LOCAL_SRC_FILES := libs/libswresample.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := swscale
LOCAL_SRC_FILES := libs/libswscale.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := cinema
LOCAL_C_INCLUDES := ffmpeg
LOCAL_SRC_FILES := \
jni-event.c \
cinema-jni.c \
util.c \
ffmpeg-recoder.c \
runffmpeg.c \
ffmpeg/ffmpeg.c \
ffmpeg/cmdutils.c \
ffmpeg/ffmpeg_opt.c \
ffmpeg/ffmpeg_filter.c
LOCAL_LDLIBS := -llog
LOCAL_CFLAGS := -Wno-deprecated-declarations
LOCAL_SHARED_LIBRARIES +=\
avcodec \
avdevice \
avfilter \
avformat \
avutil \
postproc \
swresample \
swscale
include $(BUILD_SHARED_LIBRARY)
만약, ffmpeg.c (ffmpeg.exe)를 NDK에서 사용하고 싶을 경우 아래와 같이 수정해야 한다.
- atexit()을 사용하지 않도록 해야한다. 만약 atexit()안에 사용되는 함수가 존재할 경우(e.g.
exit_program()
)해당 함수를main()
이 종료하기 직전에 호출되도록 유도해야 한다. - attribute((noreturn))과 같은 함수속성에 주의한다 (제거하면된다).
-
main()
이 종료될 때, ffmpeg.c (ffmpeg.exe)와 관련된 모든 파일의 전역변수를 초기화해주며(exit_program()
참조) 특히 ffmpeg.c를 여러번 재활용하게 될 경우avfilter_uninit()
를 호출하지 않도록 해야한다.
Color space converting
- Stackoverflow - How do I downsize a YUV420SP (NV21) frame retrieved from Android camera?
- Stackoverflow - Android (onPreviewFrame): Saving NV21 data as JPEG File
- ConvertNV21.java
- Android-MJPEG-Video-Capture-FFMPEG
- Stackoverflow - Converting NV21 to RGB using OpenCV in Android
Example
- https://github.com/yixia/FFmpeg-Android.git
- FFmpeg-Android.git 프로젝트를 참조하여 작성된 빌드 스크립트: Compile-ffmpeg-android.zip
Project site
- Github: Android-Video-Player-FFmpeg-and-Bitmap
- ffmpeg-android
- this is port of ffmpeg for android
- RockPlayer website
- FFmpeg for Android
- Java binding to FFmpeg libraries
- [추천] Building FFmpeg for Android neon, armv7, vfp and armv6, used in VPlayer for Android
Troubleshooting
arm-linux-androideabi-pkg-config not found, library detection may fail
configure작업중 pkg-config를 찾을 수 없어, 아래와 같은 메시지가 발생될 경우가 있을 수 있다.
WARNING: /home/cwlee/ndk-r8e-toolchain/bin/arm-linux-androideabi-pkg-config not found, library detection may fail.
이럴 경우에는 configure파일에서 pkg_config_default="${cross_prefix}${pkg_config_default}"
부분을 pkg_config_default="${pkg_config_default}"
로 고쳐주면 된다. 또는 /usr/bin/pkg-config
을 사용하면 된다.
UnsatisfiedLinkError Exception 발생시 대처방법
ff_av_get_cpu_flags_arm 관련 에러가 발생하면서 UnsatisfiedLinkError Exception 이 발생할 경우 FFmpeg 컴파일 시 disable-asm
옵션을 추가하면 된다. 컴파일 진행시 아래와 같은 에러문구가 출력될 수 있다.
- please_use_av_log_instead_of_fprintf
- please_use_av_log_instead_of_printf
- please_use_av_log_instead_of_perror
- time_is_forbidden_due_to_security_issues
이럴 경우, 아래와 같이 해당 심볼을 각각 un-define해주면 된다.
- #undef time
- #undef printf
- #undef fprintf
- #undef perror
See also
Favorite site
- [추천] FFmpeg을 이용한 Android 동영상 플레이어 개발 1
- [추천] FFmpeg을 이용한 Android 동영상 플레이어 개발: NHN 동영상 서비스 개발2팀
- 안드로이드 FFmpeg 동영상
- Using libavformat and libavcodec
- FFmpeg에 x264 인코더 사용방법
- NDK FFmpeg 동영상 플레이어 만들기
- Using FFmpegFrameRecorder on Android
- FFMPEG on Android
- [추천] Effective Color Conversion (YUV->RGB) for Android in Assembly
- How to Port ffmpeg (the Program) to Android?Ideas and Thoughts
- How to Build Android Applications Based on FFmpeg by An Example
- How to Build FFmpeg for Android
- NDK ffmpeg 컴파일 (neon 사용)
- NDK를 이용해 안드로이드용 library빌드시 문제점: codec_names.h 누락
- http://hoonkyu.blogspot.kr/2011/12/android-ndk-ffmpeg.html
- http://bluexmas.tistory.com/274
- http://blog.naver.com/ziippy/120138066006
- https://github.com/yixia/FFmpeg-Android
Guide
- 안드로이드에서 FFmpeg를 Shared Library로 빌드하는 방법 2
- FFmpeg 1.2 android ndk-build 성공방법 3
- How to Build FFmpeg for Android 4
- Build android r5b: How_to_build_ffmpeg_for_android-build_android_r5b.txt.zip
- Build android r6: How_to_build_ffmpeg_for_android-build_android_r6.txt.zip
Android NDK FFmpeg 컴파일 강좌
- http://www.androidpub.com/1645684 8
- http://www.androidpub.com/1646144 9
- http://www.androidpub.com/1646529 10
- http://www.androidpub.com/1646540 11
- 전체 소스 코드: http://www.androidpub.com/1648388
- 새로운 시도: http://www.androidpub.com/1690105 12
FFmpeg 라이브러리 빌드
- http://blog.daum.net/hopefullife/205 13
- http://blog.daum.net/hopefullife/207 14
- http://blog.daum.net/hopefullife/209 15
NDK FFmpeg 컴파일 방법 (중국어)
- 우분투에서 NDK r4b를 사용하여 FFmpeg 0.6.3을 컴파일하는 방법 (중국어) 16
- Mac OSX에서 NDK r5b를 사용하여 FFmpeg 0.8을 컴파일하는 방법 (중국어) 17
- 윈도우7에서 NDK r5c를 사용하여 FFmpeg 0.7.1을 컴파일하는 방법 (중국어) 18
ETC
References
-
Ffmpeg_android_video_player.pdf ↩
-
Android_ndk_ffmpeg_shared_library.pdf ↩
-
Android_ndk_ffmpeg-1.2_build_success.pdf ↩
-
How_to_build_ffmpeg_for_android.pdf ↩
-
How_to_build_ffmpeg_with_android_ndk.pdf ↩
-
Ffmpeg_porting_and_jni_library.pdf ↩
-
Ffmpeg_for_android-install_and_compile.pdf ↩
-
Android_ndk_ffmpeg_compile_01.pdf ↩
-
Android_ndk_ffmpeg_compile_02.pdf ↩
-
Android_ndk_ffmpeg_compile_03.pdf ↩
-
Android_ndk_ffmpeg_compile_04.pdf ↩
-
Ffmpeg_compile_for_android_ndk_cross_compiler.pdf ↩
-
Android_ndk_ffmpeg_library_build_01.pdf ↩
-
Android_ndk_ffmpeg_library_build_02.pdf ↩
-
Android_ndk_ffmpeg_library_build_03.pdf ↩
-
Ubuntu_android_ndk_r4b_ffmpeg_0.6.3.pdf ↩
-
Macosx_android_ndk_r5b_ffmpeg_0.8.pdf ↩
-
Windows7_android_ndk_r5c_ffmpeg_0.7.pdf ↩