본문 바로가기

Programming/Android

ffmpeg 3.2.2 with NDK build

[출처] : http://whiteduck.tistory.com/130

참고로 cygwin에서 하다보면 경로 문제로 인해서 빌드가 안되는 경우가 있다.

아래를 참고하자고!!! 나는 이렇게 해버렸다. 아예 복사를 해버렸어.. 경로가 문제 되니까.

그리고 /home/erato/android-ndk-r14b을 build.sh에 넣어주었다.

 cp /cygdrive/d/android/android-ndk-r14b-windows-x86_64/android-ndk-r14b/ . -r


근데 안된다.. 그냥 우분투에서 해라!


저는 아래와 같은 에러로... 안되네요...

ffmpegtmp폴더도 만들었는데 왜 이런 걸까요 ?


맥입니다.


Hongsungjunui-MacBook-Pro:ffmpeg hongsungjun$ ./config.sh

Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/c++/4.2.1

Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/c++/4.2.1

/Users/hongsungjun/Documents/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc is unable to create an executable file.

C compiler test failed.


If you think configure made a mistake, make sure you are using the latest

version from Git.  If the latest version fails, report the problem to the

ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.freenode.net.

Include the log file "config.log" produced by configure as this will help

solving the problem.

Hongsungjunui-MacBook-Pro:ffmpeg hongsungjun$ 


로그 파일은


END /var/folders/8t/gk5ft7ts7lq4fb28mbqg42fm0000gn/T//ffconf.goXeRHOP.c

/Users/hongsungjun/Documents/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc -marm -march=armv7-a -mfloat-abi=softfp -mfpu=neon -E -o /var/folders/8t/gk5ft7ts7lq4fb28mbqg42fm0000gn/T//ffconf.qjgCC7XV.o /var/folders/8t/gk5ft7ts7lq4fb28mbqg42fm0000gn/T//ffconf.goXeRHOP.c

check_ld cc

check_cc

BEGIN /var/folders/8t/gk5ft7ts7lq4fb28mbqg42fm0000gn/T//ffconf.goXeRHOP.c

    1 int main(void){ return 0; }

END /var/folders/8t/gk5ft7ts7lq4fb28mbqg42fm0000gn/T//ffconf.goXeRHOP.c

/Users/hongsungjun/Documents/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc -marm -march=armv7-a -mfloat-abi=softfp -mfpu=neon -march=armv7-a -c -o /var/folders/8t/gk5ft7ts7lq4fb28mbqg42fm0000gn/T//ffconf.qjgCC7XV.o /var/folders/8t/gk5ft7ts7lq4fb28mbqg42fm0000gn/T//ffconf.goXeRHOP.c

/Users/hongsungjun/Documents/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc -Wl,--fix-cortex-a8 -o /var/folders/8t/gk5ft7ts7lq4fb28mbqg42fm0000gn/T//ffconf.ExgNPyY2 /var/folders/8t/gk5ft7ts7lq4fb28mbqg42fm0000gn/T//ffconf.qjgCC7XV.o

/Users/hongsungjun/Documents/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: error: cannot open crtbegin_dynamic.o: No such file or directory

/Users/hongsungjun/Documents/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: error: cannot open crtend_android.o: No such file or directory

/Users/hongsungjun/Documents/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: error: cannot find -lc

/Users/hongsungjun/Documents/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: error: cannot find -ldl

collect2: ld returned 1 exit status

C compiler test failed.

댓글
2013.12.28 03:28:27
쿵뿌팬더

자문 자답: toolchain 문제 였습니다.

toolchain 설치를 안했었네요...


댓글
2014.01.27 18:22:04
AndroidOsh
config.sh파일을 실행 하면 다음과 같은 에러구문이 나옵니다. 
어떤식으로 접근해야 할까요?????

제가 작성한 config.sh파일입니다.
===config.sh==================================
export ANDROID_ROOT=/cygdrive/d/osh/my-android-toolchain

./configure --target-os=linux \
--arch=arm \
--enable-cross-compile \
--cc=$ANDROID_ROOT/bin/arm-linux-androideabi-gcc \
--cross-prefix=$ANDROID_ROOT/bin/arm-linux-androideabi- \
--extra-cflags="-marm -march=armv7-a -mfloat-abi=softfp -mfpu=neon" \
--extra-ldflags="-Wl,--fix-cortex-a8" \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-network \
--disable-devices \
--disable-filters
=======================================================
위와 같이 작성하였고 

실행시에는 다음과 같은 에러가 출력됩니다.
====에러 출력문=================
./config.sh: line 1: $'\357\273\277export': command not found
/bin/arm-linux-androideabi-gcc is unable to create an executable file.
C compiler test failed.

If you think configure made a mistake, make sure you are using the latest
version from Git.  If the latest version fails, report the problem to the
ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "config.log" produced by configure as this will help
solving the problem.
================================

위와 같은 에러 출력문에 나오는데....
export구문에서 commnad not found라고 나오는데 이유를 모르겠습니다.

그리고 위에서 config.h파일이 생성된다고 했는데 해당 ffmpeg폴더에 생성되는건지도 궁금합니다.

환경설정에 성공하신분들 답변 꼭 좀 부탁드리겠습니다.

댓글
2014.05.29 09:36:40
자바헬

C Compiler test fail


이 에러로 구글에 검색해본결과 우리나라 뿐만 아니라 전세계 많은 분들이 고통을 겪으시는 걸로 확인했습니다.


해결책도 정말 무긍무진했지만 구글 검색후 3페이지 정도 되는 내용을 전부 해봤는데 해결이 안되더라구요.;;;


저같은 경우 아직도 이유는 정말 모르겠지만...


극단의 조치로 toolchain을 재설치 하니까 빌드가 되었습니다;;;;


혹시 아시는분은 조언을 부탁드립니다.


아 또한 이렇게 빌드시 마지막에 


License: LGPL version 2.1 or later
Creating config.mak, config.h, and doc/config.texi...
./configure: line 1225: cmp: command not found
./configure: line 1225: cmp: command not found


요런 말이 나와서 지금 이거때문인가 안드로이드에서 빌드가 안되는데 혹시 아시는분 계신가여?

댓글
2014.05.29 09:56:56
자바헬

자답입니다.


확인결과 위의 cmp 커맨드는


cygwin 설치시 패키지중 diffutils를 설치하면 사라지는군요.



댓글
2014.09.28 01:30:46
BPinu

$ ./config.sh 명령했을때 아래 에러나시는 분들...

/cygdrive/d/my-android-toolchain/bin/arm-linux-androideabi-gcc is unable to create an executable file.

C compiler test failed.

 

12시간째 헤매다 드디어 해결했는데요.

저의 경우는 권한문제일거라고 생각은 해봤지만  d/my-android-toolchain 에 아무리 오른쪽 클릭 권한설정해도 안되었는데

 

$ chmod 777 -R /cygdrive/d/my-android-toolchain

 

이렇게 명령어로 해당폴더에 권한을 주고나서 하니까 되었어요...아 눈물이..누군가에게도 도움이 될까 하여 올려봅니다.

댓글
2015.01.11 09:28:05
허슬러

컴파일 마지막부분에 이런경고가떴는데 신경안써되는지요


WARNING: /cygdrive/d/cygwin/home/Administrator/android-toolchain/bin/arm-linux-a                                     ndroideabi-pkg-config not found, library detection may fail.

댓글
2016.02.28 16:24:01
황세희
버전 차이가 꽤 나는 지금 시점에서 글을 적어봅니다.
저같이 삽질하는 분들이 없어야하기에요..
윈도우7+cygwin+android-ndk-r10e+ffmpeg-3.0조합입니다

ffmpeg 라이브러리를 빌드할때
1. config.sh에서 경로를 /cygdrive/c/my-android-toolchain같이 절대 경로를 쓰리고 했는데..
이렇게하면 절대 안됩니다.
C:/my-android-toolchain과 같이 쓰시던지..
'cygpath -m /cygdrive/c/my-android-toolchain'과 같이 한번 변환을 해줘야합니다.
2. temp directory 설정도 위와 마찬가지입니다.
더 추가되는 사항은 C나 D 드라이브 바로 아래에 temp라는 이름으로 만들면 폴더가 리드온리로만 설정이 되는 것 같아서..
cygwin 아래의 tmp 폴더를 이용했습니다.
설치 버전에 따라 c:/cygwin/tmp 혹은 c:/cygwin64/tmp 중 하나이고..
'cygpath -m /tmp'를 하면 /tmp라는 절대 경로의 위치를 알아서 반환해줍니다.
저같은 경우는 config.sh 파일 내부에 이 3가지 변수를 설정했습니다.
3. configure 파일에서 TEMPDIR 설정하는 부분을 수정해야합니다.
(만약 config.sh에서 설정했다고 하면 주석처리라도 해줘야합니다
안그러면 나중에 실행되는 configure 스크립트 파일의 내용으로 설정이 될꺼니까요.)
4. configure에서 링크파일을 만드는 부분을 수정합니다
ln -s -f로 된 부분이 하나있는데..
cygwin에서 리눅스의 링크 파일을 정확하게 그현을 못해주기 때문에 cp -f로 그냥 복사하는걸로 교체합니다.
5. 링크 파일 문제의 연장선인데...
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'

SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
6. static 빌드는 문제가 없지만 shared 빌드의 경우 링크파일 문제가 생깁니다.
config.log 파일을 참조해서 libxxx/libxxx.so라는 링크 파일을 삭제하고 libxxx/libxxx.so.nn이라는 라이브러리 피일을 복사해서 libxxx/libxxx.so라고 바꿉니다.
그리고 계속 make를 수행하다 끝나면 make install을 해주면 됩니다

=================================================================================

|| 개발 환경 ||


1. OS : Ubuntu 16.04 ( VMware workstation 12 ) : https://www.ubuntu.com/download/desktop

2. Android Studio 2.2.3 : https://developer.android.com/studio/index.html?hl=ko

3. RAM 3GB ( VMware에서 돌아가기 위해서 충분한 RAM 이 필요 )

4. Memory : 30GB ( VMware에서 돌아가기 위해서 충분한 메모리가 필요 )



// Ubuntu 설치 이후부터 설명하며 한글은 지원하지 않은 채로 진행합니다. //

// USB 인식이 안 될 수 있습니다. VMWare 업데이트를 진행한 후에 팔로우하시기 바랍니다. //

// 저자의 ubuntu id는 user입니다. //





|| Android  studio 설치 ||


 참고 : Android 설치 환경 구축 : https://www.davidlab.net/ko/tech/how-to-setup-android-dev-env-on-ubuntu-part1/


1. JDK 설치 

$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java8-installer
view rawgistfile1.txt hosted with ❤ by GitHub



2. Android 설치

// 저자는 앞으로 다운로드하는 모든 항목은 Downloads에 모두 저장하였습니다. //



3. gmtp 설치 [ cpu가 VT-x 를 지원하지 않을 경우, 또는 실 장비 테스트가 필요한 경우 ]

// 저자의 경우에는 그냥 안되서 실 장비 테스트를 하였습니다. //

참고 : http://askubuntu.com/questions/146529/how-to-connect-mtp-devices-via-usb


$ sudo apt-get install gmtp
view rawgistfile1.txt hosted with ❤ by GitHub


4. SDK 설치

 4.1. AS(Android Studio 실행)

$ cd /home/user/Downloads/android-studio/bin/
$ ./studio.sh
view rawgistfile1.txt hosted with ❤ by GitHub


 4.2 SDK Manager

 Configure > SDKManager




 4.3 install SDK

 하고 싶은 SDK 선택



4.4 install SDK tool

 NDK 설치









|| FFmpeg 빌드 ||


 참고 : http://dev2.prompt.co.kr/77


1. FFMpeg 다운로드 :  https://ffmpeg.org/download.html#releases



2. FFMpeg 파일 이동

 미리 설치했던 NDK 폴더 하위의 sourses 폴더에 집어넣습니다.



3. Configure 파일 수정

 configure 파일은 ffmpeg-3.2.2 파일 안에 있습니다. 이 파일을 변경하지 않으면 빌드 후 so 파일이 만들어질때 *.so.57 과 같은 형식으로 만들어서 AS에 적용되지 않습니다.

#SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
#LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
#SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
#SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
view rawconfigure hosted with ❤ by GitHub



4. build script 작성

 ffmpeg-3.2.2 하위에  build_android.sh 생성



NDK=$HOME/Android/Sdk/ndk-bundle
SYSROOT=$NDK/platforms/android-16/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
function build_one
{
./configure \
--prefix=$PREFIX \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-doc \
--disable-symver \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=linux \
--arch=arm \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one
view rawbuild_android.sh hosted with ❤ by GitHub


5. build

$ chmod +x build_android.sh
$ ./build_android.sh
view rawbuild.txt hosted with ❤ by GitHub










|| JNI 환경 구축 ||


 참고 : http://dev2.prompt.co.kr/78


1. 프로젝트 생성

 일반적인 프로젝트 생성후 Project로 보기



2. 오른쪽 클릭 tool 생성 [ 편의성을 위해서 사용합니다. ]

 File > Setting 클릭 ( 키 중첩으로 Ctrl + Alt + S 가 먹히지 않습니다. )



 2.1. 추가



Name : javah
Program : /usr/lib/jvm/java-8-oracle/bin/javah
Parameters : -classpath $ClassPath$ -v -jni $FileClass$
Working directory : $ModuleFileDir$/src/main/jni
Name : ndk-build
Program : /home/user/Android/Sdk/ndk-bundle/build/ndk-build
Working directory : $ProjectFileDir$/app/src/main
Name : ndk-build clean
Program : /home/user/Android/Sdk/ndk-bundle/build/ndk-build
Parameters : clean
Working directory : $ProjectFileDir$/app/src/main
view rawgistfile1.txt hosted with ❤ by GitHub










|| FFMpeg Setting ||


 참고 : http://dev2.prompt.co.kr/79 http://dev2.prompt.co.kr/80


1. ffmpeg Android.mk 세팅 [ ffmpeg에서 so 파일을 가져오기 위한 설정 ]


 $NDK/sources/ffmpeg-3.2.2/android/arm/Android.mk 를 다음 내용으로 만듭니다.

 실제 파일이 정말로 있는지 확인한 후에 진행합니다.

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavcodec
LOCAL_SRC_FILES:= lib/libavcodec-57.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavformat
LOCAL_SRC_FILES:= lib/libavformat-57.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libswscale
LOCAL_SRC_FILES:= lib/libswscale-4.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavutil
LOCAL_SRC_FILES:= lib/libavutil-55.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavfilter
LOCAL_SRC_FILES:= lib/libavfilter-6.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libswresample
LOCAL_SRC_FILES:= lib/libswresample-2.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
view rawgistfile1.txt hosted with ❤ by GitHub


2. build.gradle 수정

 src 하위의 build.gradle을 수정합니다.



sourceSets.main {
jni.srcDirs=[]
jniLibs.srcDirs "src/main/libs"
}
view rawgistfile1.txt hosted with ❤ by GitHub



3. jni의 Android.mk, Application.mk 작성

src의 main에 jni을 생성하고 Android.mk와 Application.mk를 작성합니다.



LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := ffmpeg.c ffmpeg_opt.c cmdutils.c ffmpeg_filter.c
LOCAL_LDLIBS := -llog
LOCAL_SHARED_LIBRARIES := libavformat libavcodec libswscale libavutil libswresample libavfilter
include $(BUILD_SHARED_LIBRARY)
$(call import-module, ffmpeg-3.2.2/android/arm)
view rawAndroid.mk hosted with ❤ by GitHub


보면 알겠지만 ffmpeg라이브러리 이름을 맞춰줘야 한다.

LOCAL_MODULE은 호출되는 ModuleName이며 나중에 loadLibrary와 쌍을 이룬다.


APP_ABI=armeabi-v7a
view rawApplication.mk hosted with ❤ by GitHub

build.gradle에 다음과 같이 써야 적용된다.






|| JNI 컴파일 및 간단한 예제 ||


예제는 http://dev2.prompt.co.kr/80 와 같이 비디오 파일을 복사하는 것이며

ffmpeg 명령은


ffmpeg -i input.mp4 -filter:v crop=300:400:10:20 output.mp4


이라도 한다.


저자는 Download 폴더 밑 demo.mp4 파일을 output.mp4 파일로 복사하였다.


1. AndroidManifest.xml 변경

 외부 입력 장치 접근 권한 허가

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
view rawgistfile1.txt hosted with ❤ by GitHub


2. MainActivity.java 변경

  ndk는 NDKAdapter를 나중에 추가할 것이며, 메소드는 run_ffmepg이다.

  WRITE_EXTERNAL_STORAGE가 있어야 최신 AndroidVersion에서 외부 저장장치 접근이 가능하다.

package com.gluesys.nvr;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.gluesys.util.NDKAdapter;
import java.io.File;
public class MainActivity extends AppCompatActivity {
final int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE =0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {
// 이 권한을 필요한 이유를 설명
// It can see the file list in external storage.
if (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// 다이어로그같은것을 띄워서 사용자에게 해당 권한이 필요한 이유에 대해 설명합니다
// 해당 설명이 끝난뒤 requestPermissions()함수를 호출하여 권한허가를 요청해야 합니다
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
// 필요한 권한과 요청 코드를 넣어서 권한허가요청에 대한 결과를 받아야 합니다
}
}
else {
new NDKAdapter().run_ffmpeg();
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 권한 허가
// 해당 권한을 사용해서 작업을 진행할 수 있습니다
new NDKAdapter().run_ffmpeg();
} else {
// 권한 거부
// 사용자가 해당권한을 거부했을때 해주어야 할 동작을 수행합니다
}
return;
}
}
}
view rawMainActivity.java hosted with ❤ by GitHub


3. NDKAdapter.java 생성

  간접적으로 ffmpeg 라이브러리에 접근하기 위한 클래스이다.

package com.gluesys.util;
/**
* Created by user on 12/12/16.
*/
public class NDKAdapter {
static {
System.loadLibrary("ffmpeg");
}
public native int run_ffmpeg();
}
view rawNDKAdapter.java hosted with ❤ by GitHub



4. ffmpeg 라이브러리 가져오기 

 jni파일에 ffmpeg에 있던 *.h 밑 .c 파일을 가져온다. ( 파일 통채로 복사해도 됨 )



5. javah NDKAdapter 

 이것을 통해서 jni에 직접적으로 ffmpeg에 접근할 것을 만들어준다.

 참고로 Build > Make Project를 하지 않으면 안 만들어 진다. 



6. com_gluesys_util_NDKAdapter.h 확인

 해당 폴더에는 (5) 번에서 진행되어 컴파일된 .h파일이 있다. 안에는 사용되는 클래스와 메소드가 나오는데 이에 따라 직접적으로 연결시킬 메소드의 이름을 알수 있다. 


/*
* Class: com_gluesys_util_NDKAdapter
* Method: run_ffmpeg
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_gluesys_util_NDKAdapter_run_1ffmpeg (JNIEnv *, jobject);

7. ffmpeg.c 수정

 jni 파일에 보면 ffmpeg..c 파일이 있다. 거기에는 main()이 있는데 이를 run_ffmpeg으로 수정한다.

//int main(int argc, char **argv)
int run_ffmpeg(int argc, char **argv)
view rawgistfile1.txt hosted with ❤ by GitHub



7.1 상단에는 include와 define을 정의하고

// test - start //
#include <jni.h>
#include <android/log.h>
#define LOG_TAG "veaver"
#define LOGI(...) __android_log_print(4, LOG_TAG, __VA_ARGS__);
#define LOGE(...) __android_log_print(6, LOG_TAG, __VA_ARGS__);
// test -end //
view rawgistfile1.txt hosted with ❤ by GitHub


7.2최 하단에는 (6)에서 만들어진 메소드에 다음과 같은 소스를 기입한다. [ 실제로 테스트의 모바일 저장장치에는 /Download 밑에 demo.mp4가 있어야 한다. ]

JNIEXPORT jint JNICALL Java_com_gluesys_util_NDKAdapter_run_1ffmpeg(JNIEnv *env, jobject obj)
{
// /sdcard/input.mp4 가 있다는 가정하에 작성된 코드 입니다.
// 아래의 명령어를 수행하는 코드입니다.
// ffmpeg -i /sdcard/input.mp4 -filter:v crop=300:400:10:20 /sdcard/output.mp4
char* a0 = "ffmpeg";
char* a1 = "-i";
char* a2 = "/storage/emulated/0/Download/demo.mp4";
char* a3 = "-filter:v";
char* a4 = "crop=300:400:10:20";
char* a5 = "/storage/emulated/0/Download/output.mp4";
char* argv[6];
argv[0] = a0;
argv[1] = a1;
argv[2] = a2;
argv[3] = a3;
argv[4] = a4;
argv[5] = a5;
LOGI("call run_ffmpeg");
run_ffmpeg(6, &argv);
}
view rawgistfile1.txt hosted with ❤ by GitHub



8. 다 작성되었으면 ndk-build를 실행한다.




9. 실행 (run) 하면 메인 화면이 크다면 300x400 만큼 짤린 비디오가 생성되어 있을 것이다.


/Dowdloads

  └ demo.mp4

  └ output.mp4




 그 외 참고 자료 : 

 * Android Studio에서 JNI 연동 #1 [ http://blog.naver.com/PostView.nhn?blogId=just4u78&logNo=220630233740&parentCategoryNo=&categoryNo=&viewDate=&isShowPopularPosts=false&from=postView ]








|| 2016.12.21 일자 추가 사항 ||


 .ffmpeg 명령을 java에서 동작할 수 있도록 수정


1. MainActivity.java


String a0 = "ffmpeg";
String a1 = "-i";
String a2 = "/storage/emulated/0/Download/demo.mp4";
String a3 = "-filter:v";
String a4 = "crop=300:400:10:20";
String a5 = "/storage/emulated/0/Download/output.mp4";
String[] argv = new String[]{a0,a1,a2,a3,a4,a5};
// 동작
new NDKAdapter().run_ffmpeg(argv);
view rawMainActivity.java hosted with ❤ by GitHub




2. NDKActivity.java

public native int run_ffmpeg(String[] cmdLine); // It is thread.
view rawNDKAdapter.java hosted with ❤ by GitHub



3. ffmpeg.c


JNIEXPORT jint JNICALL Java_com_gluesys_util_NDKAdapter_run_1ffmpeg(JNIEnv *env, jobject obj, jobjectArray cmdLines)
{
jstring jstr;
jsize len = (*env)->GetArrayLength(env, cmdLines);
char **argv = (char **) malloc(len*sizeof(char *));
int i=0;
for (i=0 ; i<len; i++) {
jstr = (*env)->GetObjectArrayElement(env, cmdLines, i);
argv[i] = (char *)(*env)->GetStringUTFChars(env, jstr, 0);
}
LOGI("call run_ffmpeg");
if( len > 0)
run_ffmpeg(len, argv);
}
view rawffmpeg.c hosted with ❤ by GitHub




4. 실행 (run) 하면 메인 화면이 크다면 300x400 만큼 짤린 비디오가 생성되어 있을 것이다.


/Dowdloads

  └ demo.mp4

  └ output.mp4





출처: http://whiteduck.tistory.com/130 [이헌제의 블로그]