Android中yv12、I420、nv12、nv21之間相互轉換

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];
   }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章