Lee JaeKyu

ffmpeg in python

ffmpeg는 거의 모든 코덱을 지원한다. 그래서 ffmpeg만 이용하면 별다른 프로그램을 설치하지 않아도 된다.
mp4파일을 한 프레임씩 추출하기위해서 ffmpeg의 dll파일을 이용함. 환경은 python.
python을 접해본지 얼마 되지 않아서 공부하는 셈치고 dll파일의 함수를 실행하는 기능을 이용하기로함. 일단 ffmpeg에서 디코딩하는 예제 를 보고 python으로 옮겨봄.
옮긴것을 바탕으로 작업을 하니 ffmpeg에서 처리된 데이터를 영상처리 라이브러리에 바로 쓸 수 있어서 편리함.

시행착오

c언어의 함수를 python으로 호출할떄 포인터가 까다로워서 시행착오가 많았음.

c의 구조체를 python으로 바꾸면 이렇다.

//C
struct mystruct {
    mydatatype *myvar;
};
#python
class mystruct(Structure):
    _fields_=[
        ('myvar',POINTER(mydatatype))
    ]

일반적인 python의 클래스를 작성할떄랑은 조금 다르다. ctypes.Structure을 상속받고, _fields_안에 구조체에 있는 변수를 넣어야 한다. 이때 mydatatype를 알 수 없을때나 mydatatype을 찾아보니 엄청나게 양이 많을 때는 2가지 방법이 있다.

첫번째 방법은 POINTER(mydatatype)도 주소를 가리키는 데이터 타입이기 때문에 c_void_p로 고치면됨.

#python
class mystruct(Structure):
    _fields_=[
        ('myvar',c_void_p)
    ]

두번째 방법은 mydatatype을 선언해 놓기만 하면됨.

#python
class mydatatype(Structure):
    pass

class mystruct(Structure):
    _fields_=[
        ('myvar',POINTER(mydatatype))
    ]

mydatatype이 라이브러리 함수 내부에서만 쓰이는 경우라면 2가지 모두 무난히 돌아간다.

mystruct사용의 차이. 구조체를 선언하고 함수에 구조체에 대한 포인터로 인자를 넘길때

//C
mystruct myvar;

argbypointer(&myvar, NULL);
#python
myvar=mystruct()

argbypointer(byref(myvar), None)

NULL을 넣어야 할때는 None으로 넣으면 됨.

그리고 dll파일이 없다고 나오는 경우나
임의의 폴더에 있는 dll파일을 쓸때는 다음과 같이

#python
os.environ['PATH']+=';'+'C:\\lib'
avcodec=WinDLL('avcodec-58.dll')

os.environ[‘PATH’]에 있는 폴더에서 dll파일을 찾기때문에 해당하는 dll파일이 있는 폴더를 추가해준다.

c의 열거형인 enum은 정수형임. c_int로 처리해도 된다.