FFmpeg에서 WAV 파일 형식 감지 구현 분석

개요

FFmpeg 명령어를 사용하여 특정 파일이 WAV 오디오 파일인지 확인할 수 있습니다:

./ffmpeg -i XXX.wav

내부적으로 FFmpeg는 wav_probe 함수를 통해 파일의 형식을 판별합니다. 컨테이너 형식 탐지를 담당하는 av_probe_input_format3 함수는 등록된 모든 AVInputFormat 구조체를 순회하면서 각각의 read_probe 함수를 호출하여 해당 형식과 얼마나 일치하는지 점수를 계산합니다. WAV 파일에 대응되는 이 함수가 바로 wav_probe입니다.

wav_probe 함수 정의

wav_probe 함수는 FFmpeg 소스코드(version 5.0.3)의 libavformat/wavdec.c 파일에 다음과 같이 정의되어 있습니다:

static int wav_probe(const AVProbeData *p)
{
    if (p->buf_size <= 32)
        return 0;

    if (!memcmp(p->buf + 8, "WAVE", 4)) {
        if (!memcmp(p->buf, "RIFF", 4) || !memcmp(p->buf, "RIFX", 4))
            return AVPROBE_SCORE_MAX - 1;
        else if ((!memcmp(p->buf, "RF64", 4) ||
                  !memcmp(p->buf, "BW64", 4)) &&
                 !memcmp(p->buf + 12, "ds64", 4))
            return AVPROBE_SCORE_MAX;
    }

    return 0;
}
  • 매개변수 p: AVProbeData 구조체 포인터로, 파일 탐색에 필요한 정보를 담고 있습니다.
  • 반환값: 정수형 점수. 0은 완전히 불일치, 양수는 일정 수준 이상 일치함을 의미하며 최대값은 AVPROBE_SCORE_MAX(=100)입니다.

AVProbeData 구조체는 아래와 같습니다:

typedef struct AVProbeData {
    const char *filename;
    unsigned char *buf;
    int buf_size;
    const char *mime_type;
} AVProbeData;
  • filename: 탐색 대상 파일 경로
  • buf: 파일 앞부분 일부 바이트를 읽어 저장한 버퍼
  • buf_size: 버퍼 크기(보통 2048바이트)
  • mime_type: MIME 타입(일반적으로 NULL)

구현 원리

먼저 최소한의 헤더 길이(32바이트)보다 짧으면 WAV 형식이 아님을 판단하고 0을 반환합니다:

if (p->buf_size <= 32)
    return 0;

다음으로 WAV 파일 고유의 시그니처를 검사합니다:

  • 오프셋 8~11바이트: "WAVE"
  • 오프셋 0~3바이트: "RIFF" 또는 "RIFX"

위 조건을 만족하면 AVPROBE_SCORE_MAX - 1(즉, 99점)을 반환합니다:

if (!memcmp(p->buf + 8, "WAVE", 4)) {
    if (!memcmp(p->buf, "RIFF", 4) || !memcmp(p->buf, "RIFX", 4))
        return AVPROBE_SCORE_MAX - 1;

이때 완전한 100점을 주지 않는 이유는 ACT 형식도 동일한 WAV 헤더를 포함할 수 있어 충돌을 방지하기 위함입니다.

추가적으로 Wave64 확장 형식(RF64/BW64)도 지원됩니다:

else if ((!memcmp(p->buf, "RF64", 4) ||
          !memcmp(p->buf, "BW64", 4)) &&
         !memcmp(p->buf + 12, "ds64", 4))
    return AVPROBE_SCORE_MAX;

이 경우는 완전히 유효한 WAV 형식으로 간주되어 최고 점수인 100점을 부여받습니다.

태그: ffmpeg WAV audio-format demuxer file-probe

7월 6일 17:45에 게시됨