private YuvImage i420ToYuvImage(ByteBuffer[] yuvPlanes, int[] yuvStrides, int width, int height) { if (yuvStrides[0] != width) { return fastI420ToYuvImage(yuvPlanes, yuvStrides, width, height); } if (yuvStrides[1] != width / 2) { return fastI420ToYuvImage(yuvPlanes, yuvStrides, width, height); } if (yuvStrides[2] != width / 2) { return fastI420ToYuvImage(yuvPlanes, yuvStrides, width, height); } byte[] bytes = new byte[yuvStrides[0] * height + yuvStrides[1] * height / 2 + yuvStrides[2] * height / 2]; ByteBuffer tmp = ByteBuffer.wrap(bytes, 0, width * height); copyPlane(yuvPlanes[0], tmp); byte[] tmpBytes = new byte[width / 2 * height / 2]; tmp = ByteBuffer.wrap(tmpBytes, 0, width / 2 * height / 2); copyPlane(yuvPlanes[2], tmp); for (int row = 0; row < height / 2; row++) { for (int col = 0; col < width / 2; col++) { bytes[width * height + row * width + col * 2] = tmpBytes[row * width / 2 + col]; } } copyPlane(yuvPlanes[1], tmp); for (int row = 0; row < height / 2; row++) { for (int col = 0; col < width / 2; col++) { bytes[width * height + row * width + col * 2 + 1] = tmpBytes[row * width / 2 + col]; } } return new YuvImage(bytes, NV21, width, height, null); } private YuvImage fastI420ToYuvImage(ByteBuffer[] yuvPlanes, int[] yuvStrides, int width, int height) { byte[] bytes = new byte[width * height * 3 / 2]; int i = 0; for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { bytes[i++] = yuvPlanes[0].get(col + row * yuvStrides[0]); } } for (int row = 0; row < height / 2; row++) { for (int col = 0; col < width / 2; col++) { bytes[i++] = yuvPlanes[2].get(col + row * yuvStrides[2]); bytes[i++] = yuvPlanes[1].get(col + row * yuvStrides[1]); } } return new YuvImage(bytes, NV21, width, height, null); } private void copyPlane(ByteBuffer src, ByteBuffer dst) { src.position(0).limit(src.capacity()); dst.put(src); dst.position(0).limit(dst.capacity()); }