이 문서에서는 Visual Studio 2010에서 사용하기 위해 ffmpeg 2.1을 빌드하기 위한 방법 및 주의사항에 대해 설명합니다.
이 글을 쓰는 시점에 해당 ffmpeg 버전은 2013년 10월 경에 나온 메이저 버전입니다.
우선 ffmpeg 2.1을 Visual Studio 2010에서 빌드하기 위한 방법으로는 두 가지가 있는데 MSYS환경 및 c99 to c89 컨버터를 이용 및 Visual Studio 2010에 있는 컴파일러를 연동하여 Visual C++ 컴파일러로 컴파일을 하던지 아니면 MinGw+MSYS에서 제공하는 gcc로 컴파일 하는 방법 두 가지가 있습니다.
두 가지 방법을 해보았을 때 Visual C++ 컴파일러로 컴파일 시 컴파일 된 바이너리에 최적화가 정상적으로 되지 않아서 인코딩 시간이 gcc로 컴파일할 떄 보다 속도가 느린 문제점이 있었습니다. ( mpeg4로 인코딩 시 gcc로 컴파일한 바이너리는 avcodec_encode_video2 함수 호출 시 1ms~2ms 걸리던 부분이 동일하게 Visual C++로 컴파일한 바이너리 사용 시 avcodec_encode_video2 함수 호출 시 6~8ms 정도 소요되는 문제가 있습니다. )
이 부분은 따로 컴파일 최적화 플래그가 필요하거나 아니면 컴파일 시 c99 to c89 컨버터 때문에 그럴 수 있을꺼 같은데 여기서는 위와 같은 문제가 있어서 MinGw+MSYS+gcc로 컴파일 후에 Visual Studio로 링크를 걸어서 컴파일 하는 방법에 대해서 적겠습니다.
우선 mingw를 받아야 하는데 아래주소에서 받으실 수 있습니다.
http://sourceforge.net/projects/mingw/files/Installer/
mingw-get-setup.exe 파일을 받으면 됩니다.
해당 설치파일은 온라인 설치방식으로 설치가 됩니다.
Install을 눌러서 설치합니다.
기본적인 설치가 완료되면 주요 설치 패키지 창이 뜨는데 mingw32-base를 체크하여 gcc를 설치하고, msys-base를 체크하여 msys를 설치합니다.
메뉴의 Installation - Apply Changes 를 눌러서 설치를 진행합니다.
온라인 설치이므로 파일이 다운로드 되고 완료되면 아래와 같은 창이 뜹니다.
이제 mingw가 설치된 경로에 가서 msys\1.0 폴더안에 msys.bat을 실행시킵니다.
이 상태에서 아래와 같은 명령어를 입력하여 mingw 폴더를 마운트합니다.
( c:/mingw는 mingw가 설치된 경로입니다. 이 때 주의해야 할 부분이 경로가 c:/ 형태여야 하며, c:\이면 안됩니다. )
mount c:/mingw /mingw
우선 위와 같이 마운트가 되면 gcc명령어가 사용가능한 상태가 됩니다.
( 절대로 mingw안에 bin폴더에 gcc.exe를 msys폴더의 bin에 직접 복사하면 안됩니다. )
이제 컴파일을 위한 기본적인 환경은 셋팅이 된 상태이며, ffmpeg 2.1 소스코드를 아래주소에서 받습니다.
http://www.ffmpeg.org/releases/ffmpeg-2.1.1.tar.gz
다운로드 완료 후에 소스파일을 msys\1.0 폴더에 복사합니다.
그 후에 ./configure을 하기 전에 몇 가지 해야할 부분이 있는데 ./configure 시 pr: command not found 라는 오류가 나올 수 있기 때문에 아래주소에서 mingw 이전 버전의 파일을 받은 후에 압축을 푼 후 bin폴더의 pr.exe를 현재 우리가 설치한 mingw의 bin 폴더로 복사합니다.
yasm을 이용한 컴파일이 기본 설정이고 최적화 된 코드를 위해서 yasm을 다운로드를 먼저 받아야 합니다. ( 물론 --disable-yasm 옵션으로 어셈블리 코드를 사용하지 않을 수 있으나 추천하지 않습니다. )
아래 주소로 접속한 후에
http://yasm.tortall.net/Download.html
Win32.exe로 된 파일을 받습니다.
파일을 받은 후에 파일의 이름을 yasm.exe로 변경하여 mingw\bin 폴더로 복사합니다.
다음과 같이 ./configure를 실행시킵니다.
./configure --target-os=mingw32 --enable-cross-compile --arch=x86_64 --enable-shared
위의 configure 명령을 통해서 ffmpeg 라이브러리를 동적 라이브러리로 컴파일하고 LGPL 라이선스를 따르는 32비트 바이너리를 만들기 위한 준비를 합니다.
pkg-config 를 찾을 수 없다는 경고가 맨 마지막에 나오는데 무시해도 되며,
make 를 하여 컴파일을 하고 make install을 해서 컴파일 된 바이너리 및 라이브러리와 헤더파일을 복사합니다.
복사되는 경로는 msys\1.0 폴더의 local이라는 폴더에 생기게 됩니다.
이제 ffmpeg 2.1 을 Visual C++ 에서 사용하기 위해 ffmpeg 2.1에서 제공하는 간단한 예제를 컴파일 해봅니다.
이전에 msys\1.0\local\ 폴더안에 가보면 share\ffmpeg\exaples 라는 폴더가 있으며, 여러가지 예제코드가 있습니다.
여기서는 decoding_encoding.c 를 컴파일 해보도록 하겠습니다.
우선 새 빈 프로젝트를 Visual studio 2010에서 만든 후 속성 관리자에서 VC++ 디렉터리에서 ffmpeg 라이브러리와 헤더 파일 경로를 모두 지정합니다.
decoding_encoding.c 파일 확장자를 cpp로 바꾼 후 ( c로 할 경우 헤더파일에서 inline 부분에서 컴파일 에러가 납니다. ) 아래와 같이 ffmpeg 헤더 파일 참조 부분은 extern "C"로 감쌉니다.
extern "C"
{
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/imgutils.h>
#include <libavutil/mathematics.h>
#include <libavutil/samplefmt.h>
}
컴파일을 하게 되면 컴파일 시 에러가 나는데 일부 형변환 에러가 나는 부분은 강제로 형변환을 지정해 주면 되고 아래와 같은 코드에서 에러가 나는 부분은
c->time_base= (AVRational){1,25};
아래와 같이 변경해줍니다.
c->time_base.num = 1;
c->time_base.den = 25;
아래 에러가 나는 부분은
snprintf(buf, sizeof(buf), outfilename, *frame_count);
다음과 같이 변경합니다.
sprintf_s(buf, sizeof(buf), outfilename, *frame_count);
여기까지 완료되면 컴파일 시 다음과 같이 링크 에러가 나게 됩니다.
decoding_encoding.obj : error LNK2019: _avcodec_register_all 외부 기호(참조 위치: _main 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _av_free 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _avcodec_close 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _avcodec_free_frame 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _av_freep 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _av_free_packet 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _avcodec_encode_audio2 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _av_init_packet 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _avcodec_fill_audio_frame 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _av_malloc 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _av_samples_get_buffer_size 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _avcodec_alloc_frame 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _avcodec_open2 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _av_get_channel_layout_nb_channels 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _av_get_sample_fmt_name 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _avcodec_alloc_context3 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _avcodec_find_encoder 외부 기호(참조 위치: "void __cdecl audio_encode_example(char const *)" (?audio_encode_example@@YAXPBD@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _avcodec_decode_audio4 외부 기호(참조 위치: "void __cdecl audio_decode_example(char const *,char const *)" (?audio_decode_example@@YAXPBD0@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _avcodec_get_frame_defaults 외부 기호(참조 위치: "void __cdecl audio_decode_example(char const *,char const *)" (?audio_decode_example@@YAXPBD0@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _avcodec_find_decoder 외부 기호(참조 위치: "void __cdecl audio_decode_example(char const *,char const *)" (?audio_decode_example@@YAXPBD0@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _avcodec_encode_video2 외부 기호(참조 위치: "void __cdecl video_encode_example(char const *,int)" (?video_encode_example@@YAXPBDH@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _av_image_alloc 외부 기호(참조 위치: "void __cdecl video_encode_example(char const *,int)" (?video_encode_example@@YAXPBDH@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _av_opt_set 외부 기호(참조 위치: "void __cdecl video_encode_example(char const *,int)" (?video_encode_example@@YAXPBDH@Z) 함수)에서 확인하지 못했습니다.
decoding_encoding.obj : error LNK2019: _avcodec_decode_video2 외부 기호(참조 위치: "int __cdecl decode_write_frame(char const *,struct AVCodecContext *,struct AVFrame *,int *,struct AVPacket *,int)" (?decode_write_frame@@YAHPBDPAUAVCodecContext@@PAUAVFrame@@PAHPAUAVPacket@@H@Z) 함수)에서 확인하지 못했습니다.
E:\MinGW\msys\1.0\local\share\ffmpeg\examples\dec_enc\Debug\dec_enc.exe : fatal error LNK1120: 24개의 확인할 수 없는 외부 참조입니다.
링크 에러는 소스코드에서 아래와 같은 지시자를 통해서 라이브러리 링크를 해주면 됩니다.
#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
링킹이 성공적으로 완료되면, avcodec-55.dll, avformat-55.dll, avutil-52.dll 파일을 실행파일 경로로 복사하고 MinGw\bin 폴더에 libgcc_s_dw2-1.dll 도 같이 복사해 예제를 실행해 볼 수 있습니다.
참고로 예제 실행 시 h264를 파라메터로 줄 때에는 Codec not found가 뜨는데 LGPL로 컴파일이 되어서 이렇게 된 것이며, GPL로 컴파일하여야 h264 코덱을 사용할 수 있습니다.
'인터넷/IT > 프로그래밍' 카테고리의 다른 글
OpenSSL 빌드하기 ( Visual Studio 2010 ) 또는 libeay32.dll, ssleay32.dll 다운로드 (1) | 2014.02.21 |
---|---|
SignTool Error: No certificates were found that met all the given criteria. (0) | 2014.02.19 |
pfx 파일을 이용한 응용 프로그램 디지털 서명하기 (0) | 2014.02.19 |
Microsoft Windows SDK for Windows 7 and .NET Framework 4 설치 시 에러 해결방안 (0) | 2014.01.11 |
MinGW gcc.exe: error: CreateProcess: No such file or directory 해결방안 (0) | 2014.01.08 |
IE9 이상으로 브라우저를 업그레이드하거나, 크롬, 파이어폭스 등 최신 브라우저를 이용해주세요.