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];
   }
}

你可能感兴趣的:(音视频开发)