目录
前言
由于有些三方的SDK接收的是NV21的数据因此需要对Camerax回调的YUV420数据转为NV21数据才能满足需要
实现代码
之前在网上找了一个实现此需求的逻辑(如下),不过后来发现某些手机会出错
```
fun yuv420ToNv21(image: ImageProxy): ByteArray{
val planes = image.planes
val yBuffer: ByteBuffer = planes[0].buffer
val uBuffer: ByteBuffer = planes[1].buffer
val vBuffer: ByteBuffer = planes[2].buffer
val ySize: Int = yBuffer.remaining()
val uSize: Int = uBuffer.remaining()
val vSize: Int = vBuffer.remaining()
val size = image.width * image.height
val nv21 = ByteArray(size * 3 / 2)
yBuffer.get(nv21, 0, ySize)
vBuffer.get(nv21, ySize, vSize)
val u = ByteArray(uSize)
uBuffer.get(u)
//每隔开一位替换V,达到VU交替
var pos = ySize + 1
for (i in 0 until uSize) {
if (i % 2 == 0) {
nv21[pos] = u[i]
pos += 2
}
}
return nv21
}
```
后来通过检验使用如下逻辑可以完美解决
```
fun YUV420toNV21(image: ImageProxy): ByteArray{
val crop: Rect = image.getCropRect()
val format: Int = image.getFormat()
val width = crop.width()
val height = crop.height()
val planes: Array<ImageProxy.PlaneProxy> = image.getPlanes()
val data = ByteArray(width * height * ImageFormat.getBitsPerPixel(format) / 8)
val rowData = ByteArray(planes[0].getRowStride())
var channelOffset = 0
var outputStride = 1
for (i in planes.indices) {
when (i) {
0 -> {
channelOffset = 0
outputStride = 1
}
1 -> {
channelOffset = width * height + 1
outputStride = 2
}
2 -> {
channelOffset = width * height
outputStride = 2
}
}
val buffer: ByteBuffer = planes[i].getBuffer()
val rowStride: Int = planes[i].getRowStride()
val pixelStride: Int = planes[i].getPixelStride()
val shift = if (i == 0) 0 else 1
val w = width shr shift
val h = height shr shift
buffer.position(rowStride * (crop.top shr shift) + pixelStride * (crop.left shr shift))
for (row in 0 until h) {
var length: Int
if (pixelStride == 1 && outputStride == 1) {
length = w
buffer[data, channelOffset, length]
channelOffset += length
} else {
length = (w - 1) * pixelStride + 1
buffer[rowData, 0, length]
for (col in 0 until w) {
data[channelOffset] = rowData[col * pixelStride]
channelOffset += outputStride
}
}
if (row < h - 1) {
buffer.position(buffer.position() + rowStride - length)
}
}
}
return data
}
```