[비디오 코덱] Error resilience
비디오 코덱에서의 error resilience는 비디오 전송 중 일부 정보가 손실되었을때 이를 예방/처리하기 위한 여러 테크닉들을 통칭하는 말이다. 코덱마다 다르지만 결국 컨셉들은 비슷하다. 중요한 정보들을 한 곳에 담지 않고 여러 곳에 분산해서 담아서 일부 손실되어도 영향이 적도록 만든다든가, 주변 정보를 활용하여 손실된 정보를 복구한다든가 등의 방법들이 주로 쓰인다. 본 글에서는 (내가 공부한) H.264 코덱을 기준으로 작성하였다.
1. Slice coding
프레임을 여러 개의 '슬라이스'로 쪼개서 코딩하는 방식이다. Intra prediction을 같은 슬라이스 내의 macroblock끼리만 함으로써 슬라이스 간에 디펜던시를 없앤다. 즉 한 슬라이스가 망가졌을때 다른 슬라이스에 영향을 주지 않도록 한 것이다. 물론 inter prediction의 경우 이전 프레임의 슬라이스들에 디펜던시가 걸려있다.
흥미로운 점: 만약 슬라이스의 첫 macroblock(맨 왼쪽 위 macroblock)이 intra prediction을 사용한다면, 주변에 intra prediction으로 사용할 레퍼런스 macroblock이 없으므로 무조건 DC=128로 두는 intra prediction mode를 사용한다. (intra prediction mode들은 자신보다 왼쪽 위의 픽셀들을 이용한다.) 그러면 DC에는 거의 정보가 없으니 당연히 residual 값들이 커질거다. 사실상 거의 모든 정보가 residual에 담기는 것이다.
아래 왼쪽 그림은 임의의 비디오를 하나 가져다가 슬라이스들을 시각화해본 사진이다. max-slice-size를 1000 byte로 설정하였고 FHD video의 I frame을 이용했다. 아래 오른쪽 그림은 각 macroblock의 residual의 절댓값의 합을 시각화한 사진이다. (빨강일수록 residual 값의 합이 큼). Intra-predicted macroblock의 경우 texture가 별로 없거나 주변 픽셀들과 비슷한 부분들은 낮고, 주변과 다른 부분 (ex. corner, edge)은 높다. 또한 위에 언급한 것처럼 슬라이스의 첫 macroblock이 intra-predicted인 경우 residual에 많은 정보가 담기므로 값이 크다.
그러면 슬라이스가 전송 중에 소실되면 어떻게 될까?
일단 통째로 날라가면 당연히 그 부분이 통째로 없어진다. 그러면 슬라이스의 일부가 날라가면? 실험해본 결과, 슬라이스의 앞쪽이 얼마나 유지되냐가 관건이다. 슬라이스의 특정 부분이 날라가면 그 부분 이후부터 슬라이스 끝까지 날라간다.
-> 슬라이스를 최대한 작게 쪼개서 소실이 propagation 되는 범위를 좁히는 것이 유리하다. 하지만 그러면 슬라이스 헤더 등의 오버헤드가 발생하므로, 최적 슬라이스 크기는 중간 어디쯔음일거다.
2. Flexible Macroblock Ordering (FMO) / Arbitrary Macroblock Ordering (AMO)
Baseline, Extended profile에서만 사용 가능한 옵션이다.
일반적으로 macroblock들을 슬라이스에 담을 때 raster scan order로 담는다. 하지만 이 기능을 사용하면 임의의 순서로 담을 수 있다. 즉, macroblock - slice 매핑을 자유롭게 설정할 수 있다. 이 기능을 활용하면 아래 그림의 type 1처럼 인터리빙을 통해 특정 슬라이스가 손상되었을 때 정보를 복구하기 쉽도록 슬라이스를 구성할 수 있다. 또한 이 기능을 RoI coding과 합치면, 에러가 RoI 경계로 넘어가지 않도록 방지한다든가, RoI 영역을 담당하는 슬라이스들을 더 자주 보낸다든가 등이 가능해진다.
다만, 슬라이스를 연속적인 macroblock들로 구성하지 않고 임의의 macroblock들로 구성하다가 coding efficiency가 낮아질 수 있고 (서로 상관없는 macroblock들을 가지고 intra-prediction해야 하는 경우), 인코딩/디코딩 complexity가 높아지는 등의 단점이 있다.
확인해본 결과 상용 코덱 소프트웨어들(FFmpeg, Gstreamer 등)에서는 이 기능을 구현해놓지 않았다. H.264 reference software에만 구현되어있는데, 이 구현체는 각종 최적화가 안되어있어서 너무 느리고 실사용이 어렵다.
3. Data (slice) Partitioning
슬라이스를 통째로 보내지 않고 또 쪼개는 테크닉이다. Partition A, B, C로 쪼개는데, partition A에 가장 중요한 정보들 (슬라이스 헤더, 모션 벡터, intra prediction mode 등)을 담고 B와 C엔 덜 중요한 정보 (residuals)를 담는다. 그러면 B, C는 손실되어도 비디오 퀄리티에 영향이 적다. 따라서 A에 더 강한 FEC를 거는 등 redundancy를 줘서 전송하면 안전할 것.
4. Error concealment
위의 1,2,3은 인코딩 단계에서 사용하는 손실에 잘 대응하기 위한 예방책이었다면, 이건 손실이 발생했을 때 디코딩 단계에서 어떻게 처리할지에 대한 알고리즘이다. 간단히 말하면 주변 정보를 활용(Intrapolation / Extrapolation)하여 손실된 부분의 정보를 예측하는 방식이다. 옛날 옛적에 많은 연구들이 진행되어서 꽤 다양한 알고리즘들이 존재하는데, 상용 코덱 소프트웨어들에서 주로 쓰이는 건 아주 단순한 방식이다.
Intra-frame concealment: 주변 픽셀들의 weighted sum을 통해 빈 부분 매꾸기
Inter-frame concealment: 주변 macroblock의 모션벡터들 중, 사용했을때 luminance가 가장 매끄러워지는 모션벡터 선택해서 사용하기.
Interpolation/Extrapolation의 특성상, 손실이 bursty하면 성능이 매우 떨어진다. 활용할 수 있는 주변 정보가 없기 때문이다. 따라서 위의 FMO에서처럼 인터리빙을 하면 error concealment의 성능을 높일 수 있을 것이다.
다음 글에서는 FFmpeg에서 Error resilience가 어떻게 구현되어있는지 살펴보도록 한다.
Reference
[1] Moinard, Matthieu & Amonou, Isabelle & Duhamel, P. & Brault, Patrice. (2014). Prediction of Transformed (DCT) Video Coding Residual for Video Compression.
[2] https://en.wikipedia.org/wiki/Flexible_Macroblock_Ordering
[3] V. Varsa and M. M. Hannuksela, “Non-normative error concealment algorithms,” ITU-T SG16 Doc. VCEG-N62, 2001.
[4] AlJobouri, Laith, et al. "Error and congestion resilient video streaming over broadband wireless." Computers 4.2 (2015): 113-141.