본문 바로가기

Developement/C/C++

ffmpeg 2.8.2 에서 3.0.2 로 옮기다.


 처음 Anystreaming windows client 를 만들면서 사용했던 ffmpeg 이 2.8.1 이었던 걸로 기억 합니다. 안드로이드나 타 플랫폼에서도 사용에 지장이 없던 버젼이라 안전빵에 쓰다가 2.8.2 로 올리면서 RTSP 재생을 하고 나면 무려 50MB 씩 메모리에 남아 있는 이상한 문제에 시달리기 시작 했었습니다.

 client 자체에 워낙 다양한 기능을 누가 원해서 끼워 넣다 보니 메모리 누수가 생긴 것인가?! 하고 긴장을 하고 최대한 단순하게 만든 내 코드에 무슨 문제가 생긴 것 인가 를 무려 3일이나 고민을 했습니다. (불행히 ffmpeg 2.8.2 적용은 아주 오래 전에 했었는데 메모리 누수가 있는지 일주일 전에 알았습니다...)

 도저히 왜 메모리 누수가 생기는지 못찾고, 단지 ffmpeg 을 사용하고 나면 메모리가 남는걸 보고 저의 문제가 아님을 직감, 바로 그냥 ffmpeg 을 3.0.2 최신으로 올려 버렸습니다. 그리고 뭔가 많이 바뀐 상태를 보고 잠시 쫄았습니다만 ... 저의 경우 다음 몇가지만 변경하고 그대로 사용함은 물론 메모리 누수도 사라 졌습니다.


 먼저 변경된 몇가지는 다음과 같았습니다.


libavfilter/avcodec.h 파일이 사라짐

기존에 libavfilter/avcodec.h 가 이젠 필요 없습니다. 그래서 그냥 참조를 지우면 됩니다. (ffplay.c 를 보고 확인)

그리고 아래의 몇가지를 수정 해 줘야 합니다.


AVFrame 할당과 해제

할당은 기존에 avcodec_alloc_frame() 함수를 썻다면 이제는 av_frame_alloc() 을 쓰면 됩니다. 어렵지 않습니다. 찾아서 그냥 바꿔 주면 됨.


AVPacket 해제 변경

기존의 av_free_packet() 함수가 av_packet_unref() 으로 변경 되었습니다.

av_read_frame() 으로 패킷을 가져 와서 사용했던 안했던 간에 av_packet_unref()로 가져온 AVPacket 을 해제 해 주도록 합니다.



 그 외에도 몇가지가 추가 된 듯 한데, 오디오 볼륨 조정이 ffmpeg 자체에서 되는듯 합니다. 하지만 저는 가져온 버퍼를 DirectX 로 넘기기 때문에 swr_convert() 로 받아온 PCM 을 직접 수정할 수 있어 사용은 안했습니다.

 또한 YUV 처리 중 Magic YUV 가 추가 된 듯 한데, 언제 사용 해 볼 일이 없어서 확인은 못 했습니다만, YUV 를 사용하는 플랫폼 이라면 좀 더 획기적인? 방법을 사용할 수 있나 봅니다.


 혹시 ffmpeg 3.0.2 변경을 두려워 하시는 분들 중 ffmpeg 컴파일만 된다면 그냥 합쳐서 사용하시면 되고, 저의 경우 configure 옵션에 다음 두가지를 사용하고 있습니다. (x86 SSE,SSE2 등의 SIMD 명령을 위한 YASM 은 옵션)


COMMON_OPT="--disable-schannel --disable-iconv"

./configure $COMMON_OPT --yasmexe=$YASM $DXVA2STR


 schannel 은 SSL 과 TCL 을 이용한 https 와 같은 secure protocol 을 위한 것 인데, 제가 사용하는 시스템엔 이걸 쓸 일이 없고, 라이브러리도 없는지라 제거 했습니다. 물론 iconv 도 쓸일이 없었습니다.


혹시 ffmpeg 2.8.2 쓰시는 분들은 아예 낮은 버젼의 stable 을 쓰시던지, 3.0.2 를 쓰시기 바랍니다. 메모리 누수엥 골치를 썩게 됩니다...