GitHub ↗
CHAPTER 03 OF 10
🏭

The Compression Pipeline

압축 파이프라인 — 예측·변환·양자화·엔트로피

모든 현대 비디오 코덱(H.264·H.265·AV1)이 공유하는 4단계 파이프라인. 이 그림이 머릿속에 있으면 어느 코덱의 디테일도 자기 자리를 찾는다.

The Compression Pipeline cheatsheet
🍌 NANO BANANA CHEATSHEET · CH 03

Overview

개관

비디오 코덱은 마법의 블랙박스가 아니다. 모든 현대 코덱이 같은 파이프라인을 공유한다. H.264, H.265, AV1, VP9, VVC — 디테일은 다르지만 큰 흐름은 동일하다. 이번 장은 그 큰 그림 그 자체.

그 그림: 예측(Prediction) → 변환(Transform) → 양자화(Quantization) → 엔트로피 부호화(Entropy coding). 이걸 "PTQE"로 외워두면, 4·5·7·8장에서 나올 모든 디테일이 "아, 이건 PTQE의 어느 단계에서 무슨 일을 하는 거구나"로 자기 자리를 찾는다.

🎯 Learning Goals
  • 현대 코덱의 4단계 파이프라인을 정확한 순서로 외운다
  • 각 단계가 어떤 중복(공간/시간/시각)을 활용하는지 매핑한다
  • 양자화가 손실의 유일한 단계임을 이해한다
  • 엔트로피 코딩이 무손실 마무리임을 안다
  • in-loop filter가 왜 끝이 아니라 루프 안에 있는지 설명할 수 있다

Sections

본문

3.1 1단계 — 예측 (Prediction): 비슷한 부분 추측

압축의 첫 번째 진짜 일은 '예측'이다. 원본 블록을 그대로 저장하지 않고, 다른 데이터로부터 추측한 다음 차이만 저장한다.

두 가지 예측이 있다.

인트라 예측 (Intra): 같은 프레임 안의 옆 블록 픽셀로부터 추측. '이 블록은 위쪽 픽셀들의 평균이겠지' 또는 '왼쪽 픽셀들을 오른쪽으로 복사하면 비슷하겠지'. H.264는 9방향, H.265는 35방향, AV1은 56방향.

인터 예측 (Inter): 다른 프레임의 비슷한 블록으로부터 추측. 모션 벡터로 "이전 프레임의 (x+5, y-2) 위치에서 블록을 가져오면 거의 맞다"고 알려준다.

예측 결과: 잔차(residual) = 원본 - 예측. 예측이 잘 맞을수록 잔차가 작아진다. 다음 단계들은 이 잔차에만 적용된다.

예측의 위력: 잘 맞는 예측은 잔차를 거의 0에 가깝게 만든다. 0이 많은 데이터는 압축이 폭증한다. 코덱 성능의 절반 이상이 이 단계의 정확도에 달려 있다.

3.2 2단계 — 변환 (Transform): 주파수 도메인으로

잔차를 그대로 저장하지 않고 변환한다. 8×8 또는 16×16 블록을 DCT(Discrete Cosine Transform)로 변환하면 주파수 도메인으로 옮겨진다.

직관: 한 블록 안의 픽셀 변화를 '저주파(부드러운 그라데이션) + 고주파(날카로운 디테일)'의 조합으로 분해. DCT 결과는 한 코너에 저주파, 다른 코너에 고주파가 모인 행렬.

왜 변환을 하나? - 에너지 압축(energy compaction): 자연 이미지의 에너지가 저주파 몇 개 계수에 집중됨 → 고주파는 0에 가까움 - 양자화에 유리: 다음 단계인 양자화에서 "저주파는 정밀하게, 고주파는 거칠게" 다룰 수 있게 됨 - 시각적 중복 활용: 인간 눈이 고주파에 둔감하다는 사실을 이용 가능

DCT 자체는 가역적이다(역DCT로 완벽 복원). 손실은 다음 단계인 양자화에서만 일어난다. 자세한 수학은 챕터 4.

3.3 3단계 — 양자화 (Quantization): 손실의 유일한 자리

여기가 손실 압축의 모든 손실이 일어나는 단계. 이 한 단계만 lossy다. 나머지는 다 가역적이다.

양자화는 DCT 계수를 양자화 매트릭스로 나눈 다음 정수로 반올림. 예: 계수 47을 양자화 스텝 8로 나누면 5.875 → 6. 복원할 때 6 × 8 = 48이 되어 1만큼 손실.

핵심: 양자화 매트릭스는 균일하지 않다. 저주파 계수는 작은 스텝(정밀하게), 고주파 계수는 큰 스텝(거칠게). 이 비대칭이 "사람 눈이 못 인지하는 고주파를 더 많이 버린다"는 시각적 중복의 활용이다.

양자화 스텝의 강도를 결정하는 게 QP(Quantization Parameter) 또는 CRF(Constant Rate Factor). 둘 다 '얼마나 많이 버리느냐'를 조절. 낮을수록 정밀(고화질·고용량), 높을수록 거칠(저화질·저용량).

엔지니어가 일상에서 가장 많이 만지는 옵션이 이 QP/CRF. ffmpeg -crf 23 같은 게 바로 이 값.

3.4 4단계 — 엔트로피 부호화 (Entropy coding): 무손실 마무리

양자화 후 데이터에는 0이 잔뜩 섞여 있고, 작은 정수들이 반복된다. 이걸 무손실로 최대한 압축하는 게 엔트로피 부호화.

원리: 자주 나오는 값에 짧은 비트열, 드물게 나오는 값에 긴 비트열을 할당. Shannon이 1948년에 증명한 한계까지 압축 가능.

H.264에서 두 종류: - CAVLC (Context-Adaptive Variable Length Coding): 빠르지만 효율 낮음. Baseline profile. - CABAC (Context-Adaptive Binary Arithmetic Coding): 느리지만 10% 더 효율. Main/High profile.

H.265는 CABAC만, AV1은 SBAC(Symbol-Based Arithmetic Coding) 으로 발전.

엔트로피 부호화는 가역적이라 손실 없음. 디코더가 이 단계부터 거꾸로 복원해 나간다 — 엔트로피 디코딩 → 역양자화 → 역DCT → 예측 + 잔차 = 복원된 블록.

3.5 In-Loop Filter — 파이프라인 안에 숨은 5번째 단계

파이프라인을 4단계로 단순화했지만, 현대 코덱에는 또 하나 결정적 단계가 있다 — In-Loop Filter.

왜 필요한가? 양자화에서 손실이 생기면 블록 경계가 어색하게 보이는 블록 노이즈(blocky artifact)가 생긴다. 8×8 블록 단위로 따로 처리됐기 때문에 경계가 튀어 보임. 이걸 부드럽게 만드는 게 deblocking filter.

더 중요한 점: 이 필터가 디코더 후처리가 아니라 인코더 루프 안에 있다는 것. 왜? 다음 P/B 프레임을 예측할 때 참조 프레임으로 쓰는 게 "필터 거친 결과"여야 한다. 안 그러면 인코더(필터 거친 것 참조)와 디코더(필터 거친 것 참조) 사이에 차이가 생겨 점점 누적된다 = drift.

H.265 이후는 deblocking + SAO(Sample Adaptive Offset)까지 추가. AV1은 거기에 CDEF + Loop Restoration까지 3중 필터.

이 필터들의 누적이 최신 코덱이 같은 비트레이트에서 더 좋아 보이는 큰 이유 중 하나.

💡 Analogy · 비유
음식 배달 시스템

맥도날드의 햄버거가 어떻게 배달되는지 보자. (1) 주문 예측: AI가 "이 시간에 빅맥 100개 나갈 거다"로 미리 만들기 시작. (2) 냉동 변환: 패티를 압축·냉동해서 부피 줄임. (3) 양자화: 정확히 100g이 아니라 95~105g 사이로 그냥 둠 (사람이 알아챌 한계 안에서 손실 허용). (4) 포장 압축: 같은 모양 박스에 빈틈없이 쟁여서 트럭 한 대에 더 많이 실음.

비디오 코덱의 PTQE 파이프라인이 정확히 이렇다. 예측(주문 예측), 변환(냉동 압축), 양자화(허용 오차 안에서 손실), 엔트로피 부호화(빈틈없는 포장).

그리고 In-Loop Filter는 "배달 트럭이 흔들려서 햄버거가 살짝 어그러진 걸 매장에서 다시 정리하는 직원". 이 직원이 없으면 다음 배달 때 어그러진 햄버거를 기준으로 또 만들어서 점점 더 어그러진다 = drift.

8×8 블록 하나에 파이프라인 전체(예측 → DCT → 양자화 → 엔트로피)를 적용해 보자. 실제 H.264·H.265 인코더의 한 블록 처리 흐름을 단순화한 데모.

python
import numpy as np
from scipy.fftpack import dct, idct

# 8x8 블록 (그라데이션 + 약간 노이즈)
block = np.array([[i + j + np.random.randint(-3, 4)
                   for j in range(8)] for i in range(8)], dtype=float)
print('원본 블록:'); print(block.astype(int))

# 1) PREDICT: 단순 DC 예측 (블록 평균값)
predicted = np.full_like(block, block.mean())
residual = block - predicted
print('\n잔차(평균):', residual.mean())

# 2) TRANSFORM: 2D DCT
def dct2(x): return dct(dct(x.T, norm='ortho').T, norm='ortho')
def idct2(x): return idct(idct(x.T, norm='ortho').T, norm='ortho')
coeffs = dct2(residual)
print('\nDCT 계수 (저주파↖, 고주파↘):'); print(coeffs.round(1))

# 3) QUANTIZE: 양자화 매트릭스 (저주파는 정밀, 고주파는 거칠게)
Q = np.array([
    [16, 11, 10, 16, 24, 40, 51, 61],
    [12, 12, 14, 19, 26, 58, 60, 55],
    [14, 13, 16, 24, 40, 57, 69, 56],
    [14, 17, 22, 29, 51, 87, 80, 62],
    [18, 22, 37, 56, 68, 109,103, 77],
    [24, 35, 55, 64, 81, 104,113, 92],
    [49, 64, 78, 87, 103,121,120,101],
    [72, 92, 95, 98, 112,100,103, 99]])  # JPEG 표준 매트릭스
quantized = np.round(coeffs / Q).astype(int)
print('\n양자화 결과 (0이 잔뜩):'); print(quantized)

# 4) ENTROPY: 0의 비율
zeros = (quantized == 0).sum()
print(f'\n64개 계수 중 {zeros}개가 0 — 엔트로피 부호화의 자원')

# 디코더: 역과정
restored = idct2(quantized * Q) + predicted
print(f'\n복원 후 평균 오차: {np.abs(restored - block).mean():.2f}')

이 8×8 블록 하나에 PTQE 파이프라인이 다 들어 있다. (1) DC 예측으로 잔차 생성, (2) DCT로 주파수 도메인 변환, (3) 양자화 매트릭스로 나누어 정수화 — 여기서 64개 계수 중 절반 이상이 0이 된다. (4) 0이 많아진 데이터는 엔트로피 부호화로 압축 폭증. 디코더는 역양자화 → 역DCT → 잔차 + 예측 = 복원. 사람이 인지하기 어려운 손실(평균 오차 1~2)만 남는다.

🏭 현업에서의 평가
PTQE 파이프라인을 외우는 게 비디오 엔지니어의 시작. 면접에서 '예측 → 변환 → 양자화 → 엔트로피'를 즉답할 수 있어야 한다.

✅ 시니어가 보는 것

  • 4단계를 순서대로 즉답할 수 있는지
  • 양자화가 손실의 유일한 자리임을 정확히 안다
  • DCT가 손실이 아닌 변환임을 안다
  • in-loop filter가 왜 루프 안에 있어야 하는지(drift 방지) 설명 가능

⚠️ 레드 플래그

  • DCT가 압축이라고 생각
  • 예측을 안 거치고 바로 변환·양자화한다고 생각
  • 인코더만 알고 디코더의 역과정을 설명 못 함

🎤 예상 인터뷰 질문

  1. 비디오 코덱의 압축 파이프라인을 4단계로 설명해 주세요
  2. 양자화가 손실의 유일한 단계라는 게 무슨 뜻인가요?
  3. In-loop filter가 왜 디코더 후처리가 아니라 인코더 루프 안에 있어야 하나요?
숙달 vs 익숙함: Familiar는 'PTQE' 단어를 안다. Mastery는 각 단계가 무엇을 하는지, 어떤 중복을 활용하는지, 왜 그 순서인지를 설명할 수 있고, in-loop filter의 위치 이유까지 안다.

Key Takeaways

핵심 정리

PTQE 파이프라인

Predict → Transform → Quantize → Entropy. 모든 코덱이 공유.

예측이 가장 중요

잔차를 작게 만드는 게 압축의 절반.

Intra vs Inter

같은 프레임 안 vs 다른 프레임 참조.

DCT는 손실 없음

변환은 가역적. 손실은 다음 단계만.

양자화 = 유일한 손실

여기서만 사람 눈 인지 한계 활용.

엔트로피 = 무손실 마무리

Shannon 한계까지 압축. CABAC, SBAC.

In-Loop Filter

Drift 방지를 위해 루프 안에 위치.

코덱은 같은 그림

디테일이 다를 뿐 큰 흐름은 H.264~AV1 동일.