I420對應YUV420P,平面格式存儲,4:2:0採樣,U在前,V在後。
YV12對應YUV420P,平面格式存儲,4:2:0採樣,V在前,U在後。
NV12對應YUV420SP,半平面格式存儲,4:2:0採樣,U在前,V在後。
NV21對應YUV420SP,半平面格式存儲,4:2:0採樣,V在前,U在後。
對應的數據存儲格式是:
I420: YYYYYYYY UU VV
YV12: YYYYYYYY VV UU
NV12: YYYYYYYY UVUV
NV21: YYYYYYYY VUVU
1、NV12轉I420
/**
* NV21 is a 4:2:0 YCbCr, For 1 NV21 pixel: YYYYYYYY VUVU I420YUVSemiPlanar
* is a 4:2:0 YUV, For a single I420 pixel: YYYYYYYY UVUV Apply NV21 to
* I420YUVSemiPlanar(NV12) Refer to https://wiki.videolan.org/YUV/
*/
private void NV21toI420SemiPlanar(byte[] nv21bytes, byte[] i420bytes,
int width, int height) {
int totle = width * height; //Y數據的長度
int nLen = totle / 4; //U、V數據的長度
System.arraycopy(nv21bytes, 0, i420bytes, 0, totle);
for (int i = 0; i < nLen; i++) {
i420bytes[totle + i] = nv21bytes[totle + 2 * i];
i420bytes[totle + nLen + i] = nv21bytes[totle + 2 * i + 1];
}
}
2、YV12轉I420
private void YV12toI420(byte[]yv12bytes, byte[] i420bytes, int width, int height) {
int totle = width * height; //Y數據的長度
System.arraycopy(yv12bytes, 0, i420bytes, 0,totle);
System.arraycopy(yv12bytes, totle + totle/4, i420bytes, totle,totle/4);
System.arraycopy(yv12bytes, totle, i420bytes, totle + totle/4,totle/4);
}
3、YV12轉NV21
private void YV12toNV21(byte[]yv12bytes, byte[] nv21bytes, int width, int height) {
int totle = width * height; //Y數據的長度
int nLen = totle / 4; //U、V數據的長度
System.arraycopy(yv12bytes, 0, nv21bytes, 0, width * height);
for (int i = 0; i < nLen; i++) {
nv21bytes[totle + 2 * i + 1] = yv12bytes[totle + nLen + i];
nv21bytes[totle + 2 * i] = yv12bytes[totle + i];
}
}