Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions Live/src/main/java/com/frank/live/camera/Camera2Helper.java
Original file line number Diff line number Diff line change
Expand Up @@ -584,11 +584,15 @@ public void onImageAvailable(ImageReader reader) {
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);
}
Expand Down
126 changes: 78 additions & 48 deletions Live/src/main/java/com/frank/live/util/YUVUtil.java
Original file line number Diff line number Diff line change
@@ -1,69 +1,99 @@
package com.frank.live.util;

import android.util.Log;

/**
* Tool of transforming YUV format
* Created by frank on 2018/7/1.
*/

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

}
3 changes: 2 additions & 1 deletion doc/JNI_develop_practice.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ JNI是Java本地接口,定义Android从应用代码(以Java或kotlin编程语

### 相关介绍文章如下:
[NDK编译脚本](https://blog.csdn.net/u011686167/article/details/106458899)</br>
[JNI开发规范](https://blog.csdn.net/u011686167/article/details/81784979)</br>
[JNI开发规范](https://blog.csdn.net/u011686167/article/details/81784979)</br>
[JNI全面介绍与最佳实践](https://blog.csdn.net/u011686167/article/details/124132719)</br>