diff --git a/Live/src/main/java/com/frank/live/camera/Camera2Helper.java b/Live/src/main/java/com/frank/live/camera/Camera2Helper.java index feb8eb2..ac7fdb2 100644 --- a/Live/src/main/java/com/frank/live/camera/Camera2Helper.java +++ b/Live/src/main/java/com/frank/live/camera/Camera2Helper.java @@ -584,11 +584,15 @@ public class Camera2Helper { offset += len / 4; } - if (rotateDegree == 90) { + if (rotateDegree == 90 || rotateDegree == 180) { if (dstData == null) { dstData = new byte[len * 3 / 2]; } - YUVUtil.YUV420pRotate90(dstData, yuvData, width, height); + if (rotateDegree == 90) { + YUVUtil.YUV420pRotate90(dstData, yuvData, width, height); + } else { + YUVUtil.YUV420pRotate180(dstData, yuvData, width, height); + } if (camera2Listener != null) { camera2Listener.onPreviewFrame(dstData); } diff --git a/Live/src/main/java/com/frank/live/util/YUVUtil.java b/Live/src/main/java/com/frank/live/util/YUVUtil.java index 4786703..ff109ac 100644 --- a/Live/src/main/java/com/frank/live/util/YUVUtil.java +++ b/Live/src/main/java/com/frank/live/util/YUVUtil.java @@ -1,5 +1,7 @@ package com.frank.live.util; +import android.util.Log; + /** * Tool of transforming YUV format * Created by frank on 2018/7/1. @@ -7,63 +9,91 @@ package com.frank.live.util; public class YUVUtil { - public static byte[] ARGBtoYUV420SemiPlanar(int[] input, int width, int height) { + public static byte[] ARGBtoYUV420SemiPlanar(int[] input, int width, int height) { - final int frameSize = width * height; - byte[] yuv420sp = new byte[width * height * 3 / 2]; - int yIndex = 0; - int uvIndex = frameSize; + final int frameSize = width * height; + byte[] yuv420sp = new byte[width * height * 3 / 2]; + int yIndex = 0; + int uvIndex = frameSize; - int a, R, G, B, Y, U, V; - int index = 0; - for (int j = 0; j < height; j++) { - for (int i = 0; i < width; i++) { + int a, R, G, B, Y, U, V; + int index = 0; + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++) { - a = (input[index] & 0xff000000) >> 24; - R = (input[index] & 0xff0000) >> 16; - G = (input[index] & 0xff00) >> 8; - B = (input[index] & 0xff); + a = (input[index] & 0xff000000) >> 24; + R = (input[index] & 0xff0000) >> 16; + G = (input[index] & 0xff00) >> 8; + B = (input[index] & 0xff); - // RGB to YUV algorithm - Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16; - U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128; - V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128; + // RGB to YUV algorithm + Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16; + U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128; + V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128; - // NV21 has a plane of Y and interleaved planes of VU each sampled by a factor of 2 - // meaning for every 4 Y pixels there are 1 V and 1 U. - yuv420sp[yIndex++] = (byte) ((Y < 0) ? 0 : (Math.min(Y, 255))); - if (j % 2 == 0 && index % 2 == 0) { - yuv420sp[uvIndex++] = (byte) ((V < 0) ? 0 : (Math.min(V, 255))); - yuv420sp[uvIndex++] = (byte) ((U < 0) ? 0 : (Math.min(U, 255))); - } + // NV21 has a plane of Y and interleaved planes of VU each sampled by a factor of 2 + // meaning for every 4 Y pixels there are 1 V and 1 U. + yuv420sp[yIndex++] = (byte) ((Y < 0) ? 0 : (Math.min(Y, 255))); + if (j % 2 == 0 && index % 2 == 0) { + yuv420sp[uvIndex++] = (byte) ((V < 0) ? 0 : (Math.min(V, 255))); + yuv420sp[uvIndex++] = (byte) ((U < 0) ? 0 : (Math.min(U, 255))); + } - index++; - } + index++; + } + } + return yuv420sp; } - return yuv420sp; - } - public static void YUV420pRotate90(byte[] dstData, byte[] data, int width, int height) { - int n = 0; - int wh = width * height; - //y - for (int j = 0; j < width; j++) { - for(int i = height - 1; i >= 0; i--) { - dstData[n++] = data[width * i + j]; - } - } - //u - for (int i = 0; i < width / 2; i++) { - for (int j = 1; j <= height / 2; j++) { - dstData[n++] = data[wh + ((height/2 - j) * (width / 2) + i)]; - } + public static void YUV420pRotate90(byte[] dst, byte[] src, int width, int height) { + int n = 0; + int wh = width * height; + int halfWidth = width / 2; + int halfHeight = height / 2; + // y + for (int j = 0; j < width; j++) { + for (int i = height - 1; i >= 0; i--) { + dst[n++] = src[width * i + j]; + } + } + // u + for (int i = 0; i < halfWidth; i++) { + for (int j = 1; j <= halfHeight; j++) { + dst[n++] = src[wh + ((halfHeight - j) * halfWidth + i)]; + } + } + // v + for (int i = 0; i < halfWidth; i++) { + for (int j = 1; j <= halfHeight; j++) { + dst[n++] = src[wh + wh / 4 + ((halfHeight - j) * halfWidth + i)]; + } + } } - //v - for(int i = 0; i < width / 2; i++) { - for(int j = 1; j <= height / 2; j++) { - dstData[n++] = data[wh + wh / 4 + ((height / 2 - j) * (width / 2) + i)]; - } + + public static void YUV420pRotate180(byte[] dst, byte[] src, int width, int height) { + int n = 0; + int halfWidth = width / 2; + int halfHeight = height / 2; + // y + for (int j = height - 1; j >= 0; j--) { + for (int i = width; i > 0; i--) { + dst[n++] = src[width * j + i - 1]; + } + } + // u + int offset = width * height; + for (int j = halfHeight - 1; j >= 0; j--) { + for (int i = halfWidth; i > 0; i--) { + dst[n++] = src[offset + halfWidth * j + i - 1]; + } + } + // v + offset += halfWidth * halfHeight; + for (int j = halfHeight - 1; j >= 0; j--) { + for (int i = halfWidth; i > 0; i--) { + dst[n++] = src[offset + halfWidth * j + i - 1]; + } + } } - } }