NV12 是 YUV 格式的一種特定記憶體排列變體。
簡單來說,「YUV」是一個大分類(泛指所有將亮度與色度分開的色彩空間),而「NV12」則是這個大分類下,屬於 YUV 4:2:0 取樣、且採用半平面(Semi-Planar)記憶體排列的一種具體標準。
它們的關係可以透過以下三個核心維度來理解:
1. 隸屬與取樣關係 (Subsampling)
- YUV:包含 4:4:4、4:2:2、4:2:0 等多種色度抽樣比例。
- NV12:固定屬於 YUV 4:2:0。這代表水準與垂直方向都每 2×2(共 4 個)像素的 Y(亮度),共用一組 U 和 V(色度)。每像素平均只佔用 1.5 位元組 (12 bits)。
2. 記憶體排列方式 (Layout)
這是 NV12 與其他 YUV420 格式(如 I420)最大的差別。NV12 採用半平面(Semi-Planar)架構,在記憶體中分為兩個平面(Plane):
- Plane 1 (Y 平面):連續存放所有像素的 Y(亮度)資料。
- Plane 2 (UV 平面):將 U 和 V 資料交錯(Interleaved)存放在一起,順序為
U, V, U, V...。
記憶體排列表現樣張(以 4×2 像素為例):
3. 直觀對比:NV12 與其他常見 YUV 格式
為了讓你更清楚 NV12 在 YUV 大家族中的位置,以下直接與其他常見格式進行對比:
| 格式名稱 | YUV 取樣比例 | 記憶體架構分類 | 記憶體實際排列順序 | 常用場景 |
|---|---|---|---|---|
| NV12 | 4:2:0 | Semi-Planar (半平面) | YYYYYYYY 接著 UVUV | Direct3D、Android、硬體解碼 (GPU) |
| NV21 | 4:2:0 | Semi-Planar (半平面) | YYYYYYYY 接著 VUVU | Android 相機預設 (Camera1 API) |
| I420 (YU12) | 4:2:0 | Planar (全平面) | YYYYYYYY 接著 UU 接著 VV | 軟體視訊通訊 (WebRTC, FFmpeg) |
| YUY2 (YUYV) | 4:2:2 | Packed (打包交錯) | Y0 U0 Y1 V0 Y2 U2 Y3 V2 | USB 視訊鏡頭、早期影音擷取卡 |
為什麼 NV12 這麼受歡迎?
在現代作業系統與顯示卡(如 Intel、NVIDIA、AMD 的硬體加速解碼)中,NV12 是最被廣泛支援的內部格式。
因為它的 Y 平面與 UV 平面是分開的,顯示卡在渲染時可以直接把 Y 平面當成一張灰階紋理(Texture),UV 平面當成另一張色彩紋理,在晶片內部直接進行硬體級的色彩轉換(轉成 RGB 顯示),處理效率極高。
如果你正在編寫程式,需要知道如何將 RGB 矩陣打包成 NV12 的雙平面記憶體結構,或是需要 NV12 轉 RGB 的轉換公式,我們可以進一步討論!
NV21 是另一種極為常見的數位視訊編碼格式,屬於 YUV 4:2:0 採樣的 Semi-Planar(半平面) 結構。它最著名的身分是 Android 系統相機(Camera API)預設的預覽畫面格式。 [1, 2, 3]
基本特性
- 採樣格式:YUV 4:2:0。意味著橫向與縱向的色度(UV)都經過減半抽樣,每 4 個 Y(2x2 的像素區塊)共同分享一組 UU 和 VV。 [4, 5]
- 儲存平面(Two-Plane):
- 第一個平面(Plane 1):連續存放整張圖像所有的 Y(亮度) 資料。
- 第二個平面(Plane 2):將 V(Cr)和 U(Cb) 進行交錯(Interleaved)存放。 [6, 7, 8]
- 位元組順序(Byte Order):在 UV 平面中,它是以
V, U, V, U的順序排列(這也是它被稱為 NV21 的原因,V 在 U 前面)。 [1, 9] - 資料大小:平均每個像素僅佔 12 bits(1.5 個位元組),檔案體積比 YUY2(16 bits)小了 25%,非常利於網路傳輸與硬體解碼。 [4, 10]
NV21 與 NV12 的直接對比
這兩者經常被放在一起討論,因為它們的結構高達 99% 相同,唯一的差別在於 UV 平面的排列順序相反: [6, 11]
| 特性 | NV21 | NV12 |
|---|---|---|
| YUV 採樣 | YUV 4:2:0 Semi-Planar | YUV 4:2:0 Semi-Planar |
| Y 平面 | 先存放所有 Y | 先存放所有 Y |
| UV 平面順序 | V, U, V, U, V, U...(VU 交錯) | U, V, U, V, U, V...(UV 交錯) |
| 主要陣營 | Android 生態系相機預設格式 | iOS (Apple)、Windows (DirectX) 慣用格式 |
記憶體排列範例(以 4×2 像素的影像為例)
當影像讀入記憶體時,連續的位元組(Byte)呈現方式如下:
- NV21:
[Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8]+[V1, U1, V2, U2] - NV12:
[Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8]+[U1, V1, U2, V2][1, 4, 10]
應用與常見痛點
由於 NV21 是 Android 底层硬體直接吐出來的資料,許多行動端的影像演算法(如 OpenCV 影像處理、人臉辨識、AI 濾鏡模型)都會直接指定 NV21 作為輸入格式。 [5]
不過,如果你要把 Android 採集到的 NV21 影片流直接丟給跨平台播放器(如 Windows、iOS),或丟進視訊編碼器(如 H.264 標準通常偏好
I420/YU12 或 NV12),就必須在軟體層做一次 VU 順序對調(將 NV21 轉為 NV12),否則畫面中的人會集體「面色鐵青」,紅藍色調完全相反。 [1, 5]
沒有留言:
張貼留言