- 오디오와 비디오를 인코딩·디코딩·트랜스코딩하고 스트리밍할 수 있는 FFmpeg 프레임워크의 구조와 사용법을 다룸
-
ffmpeg, ffplay, ffprobe 등 명령줄 도구와 libavcodec, libavformat, libavfilter 등 핵심 라이브러리의 역할을 구체적으로 설명
-
AVFormatContext, AVCodecContext, AVPacket, AVFrame을 중심으로 한 스트림 분석과 디코딩 절차를 단계별로 구현
-
meson/ninja 빌드 시스템을 이용해 예제 코드를 자동으로 다운로드·컴파일하고, 샘플 미디어 파일을 분석해 결과를 출력
- FFmpeg의 내부 동작 원리와 디코딩 파이프라인 이해를 위한 실습형 입문 자료로 활용 가능
FFmpeg 패키지 구성
-
FFmpeg은 다양한 오디오·비디오 포맷을 인코딩, 디코딩, 트랜스코딩하고 네트워크를 통해 스트리밍할 수 있는 도구와 라이브러리 모음으로 구성됨
-
FFmpeg 도구
-
ffmpeg: 명령줄 기반 멀티미디어 포맷 변환 도구
-
ffplay: SDL과 FFmpeg 라이브러리를 기반으로 한 간단한 미디어 플레이어
-
ffprobe: 멀티미디어 스트림을 분석하는 도구
-
FFmpeg 라이브러리
-
libavformat: 입출력 및 muxing/demuxing 기능 제공
-
libavcodec: 인코딩/디코딩 기능 제공
-
libavfilter: 그래프 기반 필터를 통한 원시 미디어 처리
-
libavdevice: 입력/출력 장치 지원
-
libavutil: 공통 멀티미디어 유틸리티 제공
-
libswresample: 오디오 리샘플링, 샘플 포맷 변환, 오디오 믹싱 지원
-
libswscale: 색상 변환 및 이미지 스케일링 기능
-
libpostproc: 비디오 후처리(디블로킹, 노이즈 필터 등) 기능
FFmpeg 간단 플레이어
- 기본적인 FFmpeg 사용 방식은 멀티미디어 스트림을 demux하여 오디오와 비디오 스트림으로 분리하고, 이를 raw 오디오/비디오 데이터로 디코딩하는 과정
-
주요 구조체
-
AVFormatContext: 스트림의 동기화, 메타데이터, muxing을 관리하는 상위 구조체
-
AVStream: 연속적인 오디오 또는 비디오 스트림
-
AVCodec: 데이터 인코딩 및 디코딩 방식 정의
-
AVPacket: 스트림 내 인코딩된 데이터
-
AVFrame: 디코딩된 원시 비디오 프레임 또는 오디오 샘플
-
스트림 분석 및 demux 과정
-
avformat_alloc_context()로 AVFormatContext 메모리 할당
-
avformat_open_input()으로 멀티미디어 파일 열기
-
avformat_find_stream_info()로 파일 내 스트림 정보 분석
- 각 스트림의 시간 기반(time base), 프레임레이트, 시작 시간, 길이, 타입, FourCC 코드를 출력
-
avformat_close_input()으로 파일 닫기 및 메모리 해제
-
코덱 탐색 및 초기화
-
avcodec_find_decoder()로 AVStream의 코덱 ID에 맞는 디코더 탐색
- 비디오 스트림의 경우 해상도(width, height), 오디오 스트림의 경우 채널 수와 샘플레이트 출력
-
avcodec_alloc_context3()로 AVCodecContext 생성
-
avcodec_parameters_to_context()로 스트림의 코덱 파라미터를 디코더 컨텍스트에 적용
-
avcodec_open2()로 디코더 열기
-
패킷 읽기 및 디코딩
-
AVPacket과 AVFrame 구조체를 각각 인코딩된 패킷과 디코딩된 프레임 저장용으로 할당
-
av_read_frame()으로 입력 파일에서 패킷을 순차적으로 읽음
- 패킷의 stream_index를 통해 어떤 스트림에서 왔는지 식별
- 선택된 비디오 스트림(first_video_stream_index)의 패킷만 디코더로 전송
-
avcodec_send_packet()으로 패킷을 디코더에 전달
-
avcodec_receive_frame()으로 디코딩된 프레임을 반복적으로 수신
- 각 프레임의 번호, 타입(I/P/B), 포맷, PTS, 키프레임 여부 출력
-
av_packet_unref()으로 패킷 메모리 재활용
- 모든 처리가 끝나면 av_packet_free(), av_frame_free(), avcodec_free_context(), avformat_close_input()으로 메모리 해제
-
실행 및 결과 예시
- 예제 코드는 GitHub 저장소에서 제공
-
meson과 ninja를 이용해 빌드 가능 (pip3 install meson ninja)
-
meson setup build 실행 시 FFmpeg 자동 다운로드 및 설정
-
ninja -C build로 빌드 후 ./build/ffmpeg-101 sample.mp4로 실행
- 실행 결과는 파일 포맷, 스트림 정보(비디오/오디오), 코덱, 해상도, 샘플레이트, 각 패킷의 PTS 및 디코딩된 프레임 정보 출력
-
출력 예시 요약
- 비디오 스트림: H.264 (avc1), 해상도 206x80, 프레임레이트 30fps
- 오디오 스트림: AAC (mp4a), 2채널, 44.1kHz
- 각 패킷의 PTS와 프레임 타입(I/P) 이 순차적으로 표시되며, 디코딩 과정이 콘솔에 출력됨
빌드 및 실행 환경
-
필요 도구: Python, pip, meson, ninja
-
설치 명령: pip3 install meson ninja
-
빌드 절차
- 예제 압축 파일을 ffmpeg-101 폴더에 추출
-
meson setup build 실행
-
ninja -C build로 빌드
-
./build/ffmpeg-101 sample.mp4로 실행
- FFmpeg이 시스템에 설치되어 있지 않으면 자동으로 다운로드 및 구성됨