AForge.Video.FFMPEG를 최신 버전의 ffmpeg 파일로 의존성을 변경하는 방법
AForge.Video.FFMPEG.dll의 소스 코드는 AForge.NET Framework에 포함되어 있기 때문에 이를 다운로드하면 됩니다.
소스코드 - AForge.NET Framework-2.2.5.zip
; https://code.google.com/archive/p/aforge/downloads
; https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/aforge/AForge.NET%20Framework-2.2.5.zip
압축 해제 후, AForge.Video.FFMPEG 빌드와 관련된 폴더는 다음과 같습니다.
\Externals\ffmpeg - 구 버전의 ffpeg bin, lib, includ 파일 포함
\Sources\Video.FFMPEG - Video.FFMPEG.sln 솔루션 파일까지 포함한 C++/CLI 프로젝트 (x86)
보는 바와 같이 Video.FFMPEG.vcxproj 프로젝트는 \Externals\ffmpeg 폴더 하위에 있는 ffmpeg 라이브러리에 의존성을 갖기 때문에 이 폴더의 내용을 최신으로 업데이트해 주면 됩니다.
(마지막으로 릴리스된) 2.2.5 버전의 AForge.NET Framework에 포함되어 있는 AForge.Video.FFMPEG 프로젝트는 다음의 ffmpeg 라이브러리에 의존성을 갖습니다.
- avcodec-53.dll
- avformat-53.dll
- avutil-51.dll
- swresample-0.dll
- swscale-2.dll
그런데 현재(2016-10-29) ffmpeg 3.1.5 버전은,
Download FFmpeg for Windows
; https://ffmpeg.zeranoe.com/builds/
다음의 DLL들로 구성되므로,
- avcodec-57.dll
- avformat-57.dll
- avutil-55.dll
- swresample-2.dll
- swscale-4.dll
이를 \Externals\ffmpeg\bin 폴더에 복사해야 할 뿐만 아니라 컴파일을 위해 include, lib 파일들을 구해야 합니다. 이 모든 것은 FFmpeg 라이브러리와, 개발자 용 버전을 통해 구할 수 있습니다.
- ffmpeg-3.1.5-win32-shared.zip
- ffmpeg-3.1.5-win32-dev.zip
따라서, AForge Framework의 \Externals\ffmpeg 폴더 내용을 모두 삭제하고, ffmpeg-3.1.5-win32-shared.zip의 압축을 \Externals\ffmpeg 폴더에 풀고, ffmpeg-3.1.5-win32-dev.zip 내용 중에서 "include", "lib" 폴더만 \Externals\ffmpeg 폴더에 넣어 주면 됩니다.
준비는 이것으로 끝났지만, 아쉽게도 하위 호환성이 깨진 부분이 있기 때문에 빌드 시에 맞춰주어야 할 부분이 있습니다.
우선, 다음의 코드에서 오류가 발생할 텐데요.
int video_codecs[] =
{
libffmpeg::CODEC_ID_MPEG4,
libffmpeg::CODEC_ID_WMV1,
libffmpeg::CODEC_ID_WMV2,
libffmpeg::CODEC_ID_MSMPEG4V2,
libffmpeg::CODEC_ID_MSMPEG4V3,
libffmpeg::CODEC_ID_H263P,
libffmpeg::CODEC_ID_FLV1,
libffmpeg::CODEC_ID_MPEG2VIDEO,
libffmpeg::CODEC_ID_RAWVIDEO
};
int pixel_formats[] =
{
libffmpeg::PIX_FMT_YUV420P,
libffmpeg::PIX_FMT_YUV420P,
libffmpeg::PIX_FMT_YUV420P,
libffmpeg::PIX_FMT_YUV420P,
libffmpeg::PIX_FMT_YUV420P,
libffmpeg::PIX_FMT_YUV420P,
libffmpeg::PIX_FMT_YUV420P,
libffmpeg::PIX_FMT_YUV420P,
libffmpeg::PIX_FMT_BGR24,
};
CODEC_ID_???는 AV_CODEC_ID_???로 바꾸고, PIX_FMT_???은 AV_PIX_FMT_???로 바꿔주면 됩니다.
그 외의 함수들 변화는 다음의 글에 따라,
[ffmpeg.git / doc / APIchanges
; http://git.videolan.org/?p=ffmpeg.git;a=blob;f=doc/APIchanges;h=250088b24fd6597bcd3a2b50b53cbfe077d06cef;hb=1985c2e75c607ac51bfd8dc87d2957a5edf2b6f8
이런 식으로 적절하게 바꿔주면 됩니다.
av_open_input_file ==> avformat_open_input
av_find_stream_info ==> avformat_find_stream_info
avcodec_open ==> avcodec_open2
avcodec_alloc_frame ==> av_frame_alloc
av_close_input_file ==> avformat_close_input
av_write_header ==> avformat_write_header
avcodec_encode_video ==> avcodec_encode_video2
av_new_stream ==> avformat_new_stream
av_set_parameters ==> 호출 제거
그런데, 제가 ffmpeg 사용법을 잘 몰라 확신할 수 없는 것이 2가지 있습니다. 하나는 av_set_parameters 같은 경우 대응하는 함수가 없어 제거를 했다는 점과 나머지 하나는 avformat_open_input 함수가 사용법이 달라져서 (ffmpeg를 모르는 상태로) 고쳤다는 점입니다.
특히나 "av_open_input_file" 함수의 경우 "avformat_open_input"으로 대체하는데, 사용 전 반드시 다음과 같이 avformat_alloc_context를 이용해 할당을 해줘야 했습니다. (고맙게도
close 시에 avformat_free_context는 호출하지 않아도 된다고 합니다.)
static libffmpeg::AVFormatContext* open_file( char* fileName )
{
libffmpeg::AVFormatContext* formatContext = libffmpeg::avformat_alloc_context();
if ( libffmpeg::avformat_open_input( &formatContext, fileName, NULL, NULL) !=0 )
{
return NULL;
}
return formatContext;
}
이 정도 변경하고 빌드하면 정상적으로 동작하는 (것 같은) 바이너리를 얻을 수 있습니다.
(
첨부 파일은 이 글의 Video.FFMPEG.vcxproj 프로젝트를 포함합니다. 또한
github에도 올려두었습니다.)
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]