안녕하세요 ^^
마지막 강좌로 실제 컴파일을 완료하고 간단한 플레이어를 만들어 동영상을 돌려보겠습니다.
8. 간단한 Player 소스 작성 (1)
일단은 컴파일 테스트만 해보기 위해서 빈 소스를 작성해 봅니다.
g:/Root/FFmpegBasic/jni/ 폴더 밑에 BasicPlayer 폴더를 만듭니다.
다음과 같은 4개의 파일을 작성합니다.
* Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libbasicplayer LOCAL_SRC_FILES := BasicPlayer.c Interface.c LOCAL_C_INCLUDES := $(LOCAL_PATH)/../ffmpeg/ \ $(LOCAL_PATH)/../ffmpeg/libavcodec \ $(LOCAL_PATH)/../ffmpeg/libavformat \ $(LOCAL_PATH)/../ffmpeg/libswscale LOCAL_STATIC_LIBRARIES := libavformat libavcodec libswscale libavutil cpufeatures LOCAL_LDLIBS := -lz -ljnigraphics LOCAL_ARM_MODE := arm include $(BUILD_SHARED_LIBRARY) $(call import-module,android/cpufeatures)
* Interface.c
#include <jni.h> #include <android/bitmap.h> #include "BasicPlayer.h" void Java_net_jbong_FFmpegBasic_MoviePlayView_initBasicPlayer(JNIEnv *env, jobject thiz) { av_register_all(); }
* BasicPlayer.h
#ifndef BASICPLAYER_H__INCED__110326 #define BASICPLAYER_H__INCED__110326 #endif
* BasicPlayer.c
#include "avcodec.h" #include "avformat.h" #include "swscale.h" #include "BasicPlayer.h"
9. FFmpeg 컴파일
cygwin에서 g:/Root/FFmpegBasic 폴더로 이동한 후 다음 명령으로 컴파일을 수행합니다.
$ ndk-build
시간이 제법 걸립니다.
Warning 메시지가 제법 뜨겠지만 컴파일은 Error없이 잘 수행됩니다.
10. 간단한 Player 소스 작성 (2)
컴파일이 잘 되는 것을 확인 했으니 실제 폰에서 FFmpeg 가 잘 돌아가는지 테스트 해보겠습니다.
간단한 동영상 플레이어를 만듭니다.
이 동영상 플레이어는 가장 기본적인 FFmpeg 테스트 소스입니다.
음성은 나오지도 않고, 영상의 sync도 전혀 맞지 않습니다.
화면이 잘릴 수도 있고, 프로그램이 종료 될 때 자원 해제도 완전하지 않을 수 있습니다.
하지만 어찌되었던 영상이 돌아가긴 돌아갑니다. ^^
소스 파일은 첨부드리니 다운로드 받아서 적용해 보시기 바랍니다.
g:/Root/FFmpegBasic/BasicPlayer 폴더에 다음 4개 소스 파일을 넣습니다.
Android.mk, BasicPlayer.c, BasicPlayer.h, Interface.c
(아까 작성한 빈 소스 파일을 다 덮어쓰시면 됩니다)
g:/Root/FFmpegBasic/src/net/jbong/FFmpegBasic 폴더의 FFmpegBasic.java 파일도 첨부파일로 덮어씁니다.
FFmpegBasic.java 파일을 열어 아래와 같은 부분을 찾습니다.
String fname = "/mnt/sdcard/HSTest/T4_MVI_1498.AVI";
제 폰에 들어있는 동영상 파일의 경로명이 적혀 있습니다.
sdcard에 적당한 동영상 파일을 하나 넣어두고 해당 파일의 경로명으로 수정합니다.
이제 스마트폰을 연결한 후 실행해 봅니다.
동영상이 나오면 성공입니다 ^-^
11. FFmpeg 공부
이제 컴파일을 성공했지만 기본적인 플레이어를 만드는 것도 아직 많은 과정이 남아 있습니다.
다음 강좌가 도움이 될 것입니다.
http://dranger.com/ffmpeg/
총 8편의 강좌를 여러번 읽어서 완전히 이해하신 후 이 내용을 Android에 맞게 수정하시면 잘 돌아갑니다.
위의 강좌가 아주 좋긴 하지만, FFmpeg 최신 버전에 맞지 않는 부분도 많이 있고,
배포할 수 있을 정도의 플레이어를 만들기에는 기능이 부족합니다.
더 필요한 기능은 ffmpeg 폴더 밑에 ffplay.c 소스 파일을 분석해서 구현합니다.
ffplay.c는 ffmpeg와 같이 배포되는 기본 플레이어기 때문에 가장 최신 모범 답안이라고 할 수 있습니다.
소스가 다소 방대하게 느껴지기는 하지만 반복해서 읽어보면 충분히 정복 가능한 분량입니다.
물론 쉽지는 않습니다. 상당한 시행착오와 삽질이 필요하긴 합니다.
소스를 분석하시다가 종종 FFmpeg의 Doxygen 문서를 참고하시는게 좋습니다.
http://ffmpeg.org/doxygen/trunk/annotated.html
http://ffmpeg.org/doxygen/trunk/globals.html
12. 라이센스 관련
FFmpeg는 LGPL을 따릅니다.
자세한 사항은 구글링을 해보시기 바랍니다.
요점을 정리하면 다음과 같습니다.
"FFmpeg와 static 하게 link되는 소스는 모두 공개해야 합니다"
이 말은 저작권을 어기지 않게 최대한 조심한다고 할 때,
제작하신 어플의 C 코드는 일부 (또는 전부) 공개해야 할 수도 있지만
Java 코드는 전혀 공개하지 않아도 된다는 뜻입니다.
즉, "FFmpeg로 어플을 만들면 소스를 공개해야 해서 남들이 내 어플을 허락없이 막 배포하면 어쩌지?" 하는 걱정은 안하셔도 됩니다.
Java 코드 없이는 어플로 쓸 수 없을테니까요...
13. 참고 사항 및 끝내는 말
제가 강좌 첫 부분에 프로젝트 경로명을 길게 잡지 말라고 말씀드렸습니다.
너무 길게 잡으면 아래와 같은 오류가 뜰 수 있습니다.
make: execvp: /cygdrive/c/android-ndk-r5b/ [...중략...]: Argument list too long
한마디로 make 하는데 명령이 너무 길어서 처리를 못하겠다는 뜻입니다.
경로가 길어지면 이런 현상이 발생할 수 있으므로
이런 에러가 발생하면 c:/FFmpegBasic 과 같이 매우 간단한 경로로 프로젝트 폴더를 복사해서 다시 컴파일 해보시기 바랍니다.
강좌를 정신없이 적었는데 잘 되었는지 모르겠습니다.
관련 어플을 기획하거나 제작하고 계신 분들에게 조금이라도 도움이 되었으면 합니다.
긴 강좌 읽어주셔서 감사합니다 ^^
NDK 하면 할 수록 재미가 있는거 같습니다.
물론 성공해야 재미있지만요 ^^
좋은 자료 감사합니다. 나중에 함 해봐야 겠네요 ㅋㅋ
그런의미에서 추천한방~
안녕하세요. 강좌는 잘 보았습니다. ^^
컴파일 과정을 그대로 따라해보았는데요.
ndk-build 명령을 내리면 common.mk를 찾을 수 없다고 나와서. ffmpeg폴더안으로 common.mk파일을 올려놓고 다시 build명령을 내리니 아무일도 일어나질 않네요.... 아무일도 일어나지 않아서.. 어느부분을 손대야 할 지 막막해서 그런데 답변 주시면 감사하겠습니다..
^^ 읽어주셔서 감사합니다.
덧붙이기전에는 build 가 잘됬는데요 소스를 확인하기 위해서 파일을 덧붙이고 나니까.
BasicPlayer.h 104줄에서 sws_getCachedContext 과 sws_scale undefined reference 라는
오류로 인해 진행이 되지 않고 있습니다.
그래서 2개의 정의부를 찾아봤는데 안보여서 그러는데 어떻게 해야 하나요?
컴파일 마지막즈음에 에러가 나서 질문을 드립니다.
컴파일 마지막부분에 cannot find -ljnigraphics라고 나오는데요..
android내의 platform 폴더를 찾아보니 /usr/lib안에 존재하는데.. 계속 찾을 수 없다고 나오네요...
해결방법을 아신다면 답변 주시면 정말 감사하겠습니다.. ^^.
글쎄요...
C:/android-ndk-r5b/docs/STABLE-APIS.html 에 보시면 jnigraphics library 사용법이 나옵니다.
읽어보시면 알겠지만
Android.mk에
LOCAL_LDLIBS += -ljnigraphics 추가하는 거랑
c 코드에서
<android/bitmap.h> include 하는 것 외에 다른 추가할 사항은 없습니다만...
참고로 jnigraphics library는 Android API level 8 이상에서만 지원됩니다. (2.2 프로요 이상)
혹시 프로젝트를 만드실때 2.2 미만 버전을 타겟으로 하신건 아닌지요?
MAC에서 작업했는데 잘 됩니다! 감사합니다
(이상하게 0.71이나 0.8은 이전부터 컴파일 후에 안되서 0.63이용했습니다 iOS에서는 잘 되는데 모르겠네요)
실제로 소프트웨어 디코딩보다 2배정도 성능향상이 있네요 (감동)
decode랑 sws_scale 양쪽 모두 향상이 되네요
다시 한번 감사 인사 드립니다.
make 에서
Argument list too long
에러가 나왔는데요. 이것을 path 가 긴 경우인가요?
c:\workspace\FFmpegBasic 이라고 만들었는데요.
ndk-build 에서 명령어를 찾을 수 없다고 나와서 /cygdrive/c/android-ndk-r6/ndk-build 라고 넣었거든요. 혹시 이 문제인가 싶어서 컴퓨터 설정에 Path 에 ndk 디렉토리 추가하고, C:/ 밑으로 디렉토리 옮기고 다시 시도중입니다 ^^ 컴파일 완료되었네요. 감사합니다.
System.loadLibrary("basicplayer");
이 부분에서 계속 죽는데... 무슨 일 때문일가요?!
올려주신 프로젝트도 동일한 부분에서 죽는데...ㅠㅠ
음 잘 사용하고 있었는데 갚자기 다음과 같은 에러가 나네요. 왜 그럴까요?
In file included from C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/intmath.h:31,
from C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/common.h:99,
from C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/avutil.h:125,
from C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/imgutils.h:27,
from C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/vp8.c:25:
C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/arm/intmath.h: In function 'get_quants':
C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/arm/intmath.h:81: warning: asm operand 2 probably doesn't match constraints
C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/arm/intmath.h:81: warning: asm operand 2 probably doesn't match constraints
C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/arm/intmath.h:81: warning: asm operand 2 probably doesn't match constraints
C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/arm/intmath.h:81: warning: asm operand 2 probably doesn't match constraints
C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/arm/intmath.h:81: warning: asm operand 2 probably doesn't match constraints
C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/arm/intmath.h:81: warning: asm operand 2 probably doesn't match constraints
C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/arm/intmath.h:81: error: impossible constraint in 'asm'
C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/arm/intmath.h:81: error: impossible constraint in 'asm'
C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/arm/intmath.h:81: error: impossible constraint in 'asm'
C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/arm/intmath.h:81: error: impossible constraint in 'asm'
C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/arm/intmath.h:81: error: impossible constraint in 'asm'
C:/SRC/FFmpegBasic/jni/ffmpeg/libavcodec/../libavutil/arm/intmath.h:81: error: impossible constraint in 'asm'
make: *** [/cygdrive/c/SRC/FFmpegBasic/obj/local/armeabi-v7a/objs-debug/avcodec/vp8.o] Error 1
어제 MinGW/MSYS를 설치하긴 했습니다만 혹시 그 것과 관련이 있는것일까요?
android sdk-r12-windows
android-ndk-r6-windows
FFmpeg0.8.1
에서 컴파일 성공하였습니다.
개발환경 여기까지 지장없었습니다.^^
음 제 개발환경에서는 0.8.1 소스가 계속 위에서 말했던 컴파일 에러가 나네요.
그래서 이것저것 다 해보고 있습니다. 그러다 발견한것이 컴파일 할때 -mfpu=neon 옵션이 적용되고 있지 않더라구요.
config.sh의 결과로 나오는...
config.log에서는 확실히 -march=armv7-a -mfloat-abi=softfp -mfpu=neon 옵션이 정상적으로 적용되어서
테스트컴파일이 되고 있는것이 확인되었습니다.
하지만 실제 빌드를 해보면...아래 빨강색처럼 neon 옵션이 vfp 옵션으로 변경되어 있습니다.
ndk-build V=1 -B <== 로그 보는 명령어
/cygdrive/c/android_ndk/android-ndk-r6/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-gcc -MMD -MP -MF C:/FFmpegBasic/obj/local/armeabi-v7a/objs-debug/basicplayer/BasicPlayer.o.d.org -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -O2 -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit
=300 -IC:/FFmpegBasic/jni/BasicPlayer/../ffmpeg/ -IC:/FFmpegBasic/jni/BasicPlaye
r/../ffmpeg/libavcodec -IC:/FFmpegBasic/jni/BasicPlayer/../ffmpeg/libavformat -I
C:/FFmpegBasic/jni/BasicPlayer/../ffmpeg/libswscale -IC:/android_ndk/android-ndk
-r6/sources/android/cpufeatures -IC:/FFmpegBasic/jni/BasicPlayer -DANDROID -Wa,
--noexecstack -O0 -g -IC:/android_ndk/android-ndk-r6/platforms/android-8/arch-ar
m/usr/include -c C:/FFmpegBasic/jni/BasicPlayer/BasicPlayer.c -o C:/FFmpegBasic
/obj/local/armeabi-v7a/objs-debug/basicplayer/BasicPlayer.o
이거 저만 그런건가요? 정말 강좌 (1/4 ~4/4)까지 꼼꼼히 읽어보고 비교해봤는데..안되네요. ㅠㅠ
cofig.sh를 하고 나면 다음과 같은 warning이 나긴 하는데...이거 때문인가요? 저만 나나요?
WARNING: /cygdrive/c/android_toolchain/bin/arm-linux-androideabi-pkg-config not
found, library detection may fail.
WARNING: Compiler does not indicate floating-point ABI, guessing soft.
좀 지났는데 지금은 잘 되시는지 모르겠네요~ ^^
저는 잘 컴파일 됩니다만...
일단 neon 옵션의 경우에는...
config.sh 한 로그에 -mfpu=neon 이 있던 없던 그건 실제 빌드시에는 별 관계가 없구요 (안드로이드 빌드 시스템을 쓰므로)
Android.mk를 작성할 때 해당 소스파일 뒤에 .neon 접미사가 붙어야만 합니다.
(3/4 강좌 참고, common.mk 가 하는 역할이 적절한 접미사 자동으로 붙여주고 그런 것 입니다.)
맨 아래 warning은 저도 뜹니다. ^^
신경 안쓰서도 될 듯 합니다.
혹시 BasicPlayer컴파일 중에 android/bitmap.h: No such file... 이라고 에러 발생되는 분 없으신가요?
이 에러를 어떻게 해결해야할지 감이 안옵니다. 누구 도움 좀 부탁드립니다.
BasicPlayer.c 의 av_open_input_file() 을 av_open_input_stream으로 수정할경우 네트워크로 받은 데이타를 재생시킬 수 있나요?
configure할때 네트워크 enable 시키고요;;
android sdk-19
android-ndk-r7
ADT 17
FFmpeg 0.8.11
Android 2.3.3, API 10
강좌 (1)의 toolchain 설치는 platform 9로 했습니다.
위와 같이 설정해서 성공했습니다. 작성자분이 설명하신대로 따라했구요.
FFmpeg를 0.8위로 올리면 lib폴더 안의 Makefile들이 달라지는데
어떻게 수정해야할지 몰라서 0.8로 내려왔습니다.
FFmpeg 버전만 0.8로 맞추면 다른건 바꿔도 되는것 같습니다.
다음 파일도 도움이 될것같습니다.(아직 안읽어봤어요)
강좌 잘보고 있습니다.
미숙한 관계로 삽질하면서 열심히 쫒아가고 있습니다.
막히는 부분이 있어서 문의 드립니다.
1. 이상하게 windows7 64bit에서 Cygwin을 실행하였으나 Permission Error가 처리되지 않네요..ㅠ_ㅠ 혹여 방법아시나요?
(웹에서 실행방법이라고 나온거 거의 다 해봤습니다.ㅠㅠ) 혹여나 강좌랑 똑같이 폴더 경로를 맞추니 이 부분은 해결되네요. 역시 권한문제가 어렵네요.;;
--> ndk-build 실행후 에러가 나오는데요.
<중략>
from incompatible pointer type
./libavutil/imgutils.h:112:6: note: expected ‘const uint8_t **’ but argument is of type ‘uint8_t **’
CC libavfilter/vsrc_nullsrc.o
CC libavfilter/x86/gradfun.o
AR libavfilter/libavfilter.a
make: *** `all'에서 필요로 하는 타겟 `libavformat/libavformat.a'를 만들 규칙이 없습니다. 멈춤.
이건 왜 그럴까요??
2. windows7 64bit , Ubuntu 10.04, android-ndk-r8, ffmpeg-0.11 환경으로 연습중입니다.
ndk-build를 실행하니 다음과 같은 에러가 발생했습니다.
root@ubuntu:/home/qwerty/Works/workspace/FFmpegBasic# ndk-build
jni/ffmpeg/libavcodec/Android.mk:11: jni/ffmpeg/libavcodec/c/Makefile: No such file or directory
install prefix /usr/local
source path .
C compiler /home/qwerty/Tools/android-ndk-r8/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc
ARCH c (generic)
혹시 이 문제가 왜 발생하는지 아시나요? 몇일째 이걸로 고생중입니다. 흐엉엉
강좌 너무 잘보고 갑니다.^^
제 나름대로 생각한 음악 플레이어를 만들어보려 했는데..
몇가지 부분에서 NDK 사용이 불가피하더라구요..
공부하는데 어려움이 있어 이것저것 찾아보다가..
좋은 강좌 보고갑니다.
예제 적용하니 영상 잘 뜨네요 ^^ 너무 감사해요 ㅎ
예제소스를 돌리면서 깨달았는데 패키지 경로를 다르게 했네요 ㅠㅠ net/jbong/FFmpegBasic 이라고 해야하는데
package com.example.ffmpegbasic; 이 되버렸네요
FFmpegBasic.java 첫줄 수정말고는 또 이 패키지 네임으로 인해서 영향받는 부분은 없는건가요 ? ㅠㅠ 아니면 폴더이름을 net과 jbong으로 바꾸려고 했는데 그것도 좀 정상적인게 아닌 것 같아서 불안하네요 폴더 이름을 바꿔도 될까요? 아니면 그냥 지금처럼 써도 문제 없을까요?
첨부파일 다운이 안되네요 ㅠㅠ 수정좀 해주시면 감사하겠습니다.
혹시 파일 가지고 계신분 sungjun818@nate.com 로 좀 보내주시면 감사하겠습니다! ㅠㅠ
ndk-build 시 뜨는 에러입니다. ㅠㅠ ndk 안에서 제공해주는 파일에서 에러가 나는것같은데 어떻게해야할까요??
ndk 다른 버전을 설치해야할까요? 아니면 다른 문제일까요?ㅠ 아시는분 조언좀 해주시면 감사하겠습니다!
다른건 다 성공했는데 마지막 ndk-build 하면 Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: /cygdrive/f/rc/ffmpegbasic/jni/Android.mk /home/administrator/android-ndk-r10d/build/core/add-application.mk:199: *** Android NDK: Aborting... . 멈춤.
이란 에러를 뿜어내고 진행이 안되네요 구글링 해봐도 제대로 안나오고요 뭐가 문제일까요?? ㅠㅠ
지금까지 어찌어찌해서 잘따라왔는데 이번강좌의 ndk-build에서 다음과 같은 오류가 납니다.
$ ndk-build
jni/ffmpeg-2.5.2/libavcodec/Android.mk:13: jni/ffmpeg-2.5.2/libavcodec/../common.mk: No such file or directory
jni/ffmpeg-2.5.2/libavformat/Android.mk:11: jni/ffmpeg-2.5.2/libavformat/../common.mk: No such file or directory
jni/ffmpeg-2.5.2/libavutil/Android.mk:11: jni/ffmpeg-2.5.2/libavutil/../common.mk: No such file or directory
jni/ffmpeg-2.5.2/libswscale/Android.mk:11: jni/ffmpeg-2.5.2/libswscale/../common.mk: No such file or directory
make: *** No rule to make target 'jni/ffmpeg-2.5.2/libswscale/../common.mk'. 멈춤.
대충 내용을보니 common.mk 파일을 못찾는거같은데요 분명 이전강좌에서 넣으라는곳에 다 넣었고 스펠링도 맞는데 왜이럴까요?
정말 대단한 열정입니다.
남은그루터기님의 열정이 존경스럽네요.
늘 행복하세요..^^