Feature: change y/u/v plane to yuv

pull/209/head
xufuji456 2 years ago
parent 2ca0bd97a5
commit f9f146245b
  1. 14
      Live/src/main/cpp/RtmpPusher.cpp
  2. 23
      Live/src/main/cpp/VideoStream.cpp
  3. 2
      Live/src/main/cpp/VideoStream.h
  4. 17
      Live/src/main/java/com/frank/live/LivePusherNew.java
  5. 33
      Live/src/main/java/com/frank/live/camera/Camera2Helper.java
  6. 2
      Live/src/main/java/com/frank/live/camera/Camera2Listener.java
  7. 2
      Live/src/main/java/com/frank/live/listener/OnFrameDataCallback.java
  8. 2
      Live/src/main/java/com/frank/live/stream/VideoStream.java
  9. 8
      Live/src/main/java/com/frank/live/stream/VideoStreamNew.java

@ -173,23 +173,13 @@ RTMP_PUSHER_FUNC(void, native_1start, jstring path_) {
env->ReleaseStringUTFChars(path_, path); env->ReleaseStringUTFChars(path_, path);
} }
RTMP_PUSHER_FUNC(void, native_1pushVideo, jbyteArray yuv, jbyteArray y, jbyteArray u, jbyteArray v) { RTMP_PUSHER_FUNC(void, native_1pushVideo, jbyteArray yuv, jint camera_type) {
if (!videoStream || !readyPushing) { if (!videoStream || !readyPushing) {
return; return;
} }
if (yuv) {
jbyte *yuv_plane = env->GetByteArrayElements(yuv, JNI_FALSE); jbyte *yuv_plane = env->GetByteArrayElements(yuv, JNI_FALSE);
videoStream->encodeVideo(yuv_plane, nullptr, nullptr, nullptr); videoStream->encodeVideo(yuv_plane, camera_type);
env->ReleaseByteArrayElements(yuv, yuv_plane, 0); env->ReleaseByteArrayElements(yuv, yuv_plane, 0);
} else if (y && u && v) {
jbyte *y_plane = env->GetByteArrayElements(y, JNI_FALSE);
jbyte *u_plane = env->GetByteArrayElements(u, JNI_FALSE);
jbyte *v_plane = env->GetByteArrayElements(v, JNI_FALSE);
videoStream->encodeVideo(nullptr, y_plane, u_plane, v_plane);
env->ReleaseByteArrayElements(y, y_plane, 0);
env->ReleaseByteArrayElements(u, u_plane, 0);
env->ReleaseByteArrayElements(v, v_plane, 0);
}
} }
RTMP_PUSHER_FUNC(void, native_1setAudioCodecInfo, jint sampleRateInHz, jint channels) { RTMP_PUSHER_FUNC(void, native_1setAudioCodecInfo, jint sampleRateInHz, jint channels) {

@ -82,21 +82,22 @@ void VideoStream::setVideoCallback(VideoCallback callback) {
this->videoCallback = callback; this->videoCallback = callback;
} }
void VideoStream::encodeVideo(int8_t *data, int8_t *y_plane, int8_t *u_plane, int8_t *v_plane) { void VideoStream::encodeVideo(int8_t *data, int8_t camera_type) {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (data) { if (camera_type == 1) {
//y memcpy(pic_in->img.plane[0], data, yLen); // y
memcpy(pic_in->img.plane[0], data, yLen);
//uv
for (int i = 0; i < yLen/4; ++i) { for (int i = 0; i < yLen/4; ++i) {
*(pic_in->img.plane[1] + i) = *(data + yLen + i * 2 + 1); *(pic_in->img.plane[1] + i) = *(data + yLen + i * 2 + 1); // u
*(pic_in->img.plane[2] + i) = *(data + yLen + i * 2); *(pic_in->img.plane[2] + i) = *(data + yLen + i * 2); // v
} }
} else if (y_plane && u_plane && v_plane) { } else if (camera_type == 2) {
memcpy(pic_in->img.plane[0], y_plane, (size_t) yLen); int offset = 0;
memcpy(pic_in->img.plane[1], u_plane, (size_t) yLen / 4); memcpy(pic_in->img.plane[0], data, (size_t) yLen); // y
memcpy(pic_in->img.plane[2], v_plane, (size_t) yLen / 4); offset += yLen;
memcpy(pic_in->img.plane[1], data + offset, (size_t) yLen / 4); // u
offset += yLen / 4;
memcpy(pic_in->img.plane[2], data + offset, (size_t) yLen / 4); // v
} else { } else {
return; return;
} }

@ -17,7 +17,7 @@ public:
void setVideoEncInfo(int width, int height, int fps, int bitrate); void setVideoEncInfo(int width, int height, int fps, int bitrate);
void encodeVideo(int8_t *data, int8_t *y_plane, int8_t *u_plane, int8_t *v_plane); void encodeVideo(int8_t *data, int8_t camera_type);
void setVideoCallback(VideoCallback videoCallback); void setVideoCallback(VideoCallback videoCallback);

@ -148,12 +148,8 @@ public class LivePusherNew implements OnFrameDataCallback {
native_pushAudio(data); native_pushAudio(data);
} }
private void pushVideo(byte[] data) { private void pushVideo(byte[] data, int cameraType) {
native_pushVideo(data, null, null, null); native_pushVideo(data, cameraType);
}
private void pushVideo(byte[] y, byte[] u, byte[] v) {
native_pushVideo(null, y, u, v);
} }
@Override @Override
@ -179,11 +175,9 @@ public class LivePusherNew implements OnFrameDataCallback {
} }
@Override @Override
public void onVideoFrame(byte[] yuv, byte[] y, byte[] u, byte[] v) { public void onVideoFrame(byte[] yuv, int cameraType) {
if (yuv != null) { if (yuv != null) {
pushVideo(yuv); pushVideo(yuv, cameraType);
} else if (y != null && u != null && v != null) {
pushVideo(y, u, v);
} }
} }
@ -199,8 +193,7 @@ public class LivePusherNew implements OnFrameDataCallback {
private native void native_pushAudio(byte[] data); private native void native_pushAudio(byte[] data);
// compat for Camera1 and Camera2 private native void native_pushVideo(byte[] yuv, int cameraType);
private native void native_pushVideo(byte[] yuv, byte[] y, byte[] u, byte[] v);
private native void native_stop(); private native void native_stop();

@ -525,10 +525,8 @@ public class Camera2Helper {
} }
private class OnImageAvailableListenerImpl implements ImageReader.OnImageAvailableListener { private class OnImageAvailableListenerImpl implements ImageReader.OnImageAvailableListener {
private byte[] data = null; private byte[] temp = null;
private byte[] yPlane; private byte[] yuvData = null;
private byte[] uPlane;
private byte[] vPlane;
private final ReentrantLock lock = new ReentrantLock(); private final ReentrantLock lock = new ReentrantLock();
@Override @Override
@ -538,32 +536,28 @@ public class Camera2Helper {
Image.Plane[] planes = image.getPlanes(); Image.Plane[] planes = image.getPlanes();
lock.lock(); lock.lock();
int offset = 0;
int width = image.getWidth(); int width = image.getWidth();
int height = image.getHeight(); int height = image.getHeight();
if (yPlane == null) { int len = width * height;
yPlane = new byte[width * height]; if (yuvData == null) {
uPlane = new byte[width * height / 4]; yuvData = new byte[len * 3 / 2];
vPlane = new byte[width * height / 4];
} }
planes[0].getBuffer().get(yuvData, offset, len);
planes[0].getBuffer().get(yPlane); offset += len;
for (int i = 1; i < planes.length; i++) { for (int i = 1; i < planes.length; i++) {
int srcIndex = 0, dstIndex = 0; int srcIndex = 0, dstIndex = 0;
int rowStride = planes[i].getRowStride(); int rowStride = planes[i].getRowStride();
int pixelsStride = planes[i].getPixelStride(); int pixelsStride = planes[i].getPixelStride();
ByteBuffer buffer = planes[i].getBuffer(); ByteBuffer buffer = planes[i].getBuffer();
if (data == null || data.length != buffer.capacity()) { if (temp == null || temp.length != buffer.capacity()) {
data = new byte[buffer.capacity()]; temp = new byte[buffer.capacity()];
} }
buffer.get(data); buffer.get(temp);
for (int j = 0; j < height / 2; j++) { for (int j = 0; j < height / 2; j++) {
for (int k = 0; k < width / 2; k++) { for (int k = 0; k < width / 2; k++) {
if (i == 1) { yuvData[offset + dstIndex++] = temp[srcIndex];
uPlane[dstIndex++] = data[srcIndex];
} else if (i == 2) {
vPlane[dstIndex++] = data[srcIndex];
}
srcIndex += pixelsStride; srcIndex += pixelsStride;
} }
if (pixelsStride == 2) { if (pixelsStride == 2) {
@ -572,10 +566,11 @@ public class Camera2Helper {
srcIndex += rowStride - width / 2; srcIndex += rowStride - width / 2;
} }
} }
offset += len / 4;
} }
if (camera2Listener != null) { if (camera2Listener != null) {
camera2Listener.onPreviewFrame(yPlane, uPlane, vPlane); camera2Listener.onPreviewFrame(yuvData);
} }
lock.unlock(); lock.unlock();
} }

@ -7,7 +7,7 @@ public interface Camera2Listener {
void onCameraOpened(Size previewSize, int displayOrientation); void onCameraOpened(Size previewSize, int displayOrientation);
void onPreviewFrame(byte[] y, byte[] u, byte[] v); void onPreviewFrame(byte[] yuvData);
void onCameraClosed(); void onCameraClosed();

@ -13,7 +13,7 @@ public interface OnFrameDataCallback {
void onAudioCodecInfo(int sampleRate, int channelCount); void onAudioCodecInfo(int sampleRate, int channelCount);
void onVideoFrame(byte[] yuv, byte[] y, byte[] u, byte[] v); void onVideoFrame(byte[] yuv, int cameraType);
void onVideoCodecInfo(int width, int height, int frameRate, int bitrate); void onVideoCodecInfo(int width, int height, int frameRate, int bitrate);
} }

@ -62,7 +62,7 @@ public class VideoStream extends VideoStreamBase implements Camera.PreviewCallba
@Override @Override
public void onPreviewFrame(byte[] data, Camera camera) { public void onPreviewFrame(byte[] data, Camera camera) {
if (isLiving && mCallback != null) { if (isLiving && mCallback != null) {
mCallback.onVideoFrame(data, null, null, null); mCallback.onVideoFrame(data, 1);
} }
} }

@ -128,14 +128,12 @@ public class VideoStreamNew extends VideoStreamBase
/** /**
* Camera2 preview frame data * Camera2 preview frame data
* *
* @param y plane of y * @param yuvData data of yuv
* @param u plane of u
* @param v plane of v
*/ */
@Override @Override
public void onPreviewFrame(byte[] y, byte[] u, byte[] v) { public void onPreviewFrame(byte[] yuvData) {
if (isLiving && mCallback != null) { if (isLiving && mCallback != null) {
mCallback.onVideoFrame(null, y, u, v); mCallback.onVideoFrame(yuvData, 2);
} }
} }

Loading…
Cancel
Save