Skip to content
Snippets Groups Projects
Commit f7f52cef authored by Leo Ma's avatar Leo Ma
Browse files

Fix GetDirectBufferAddress bug in jni for Nexus


Signed-off-by: default avatarLeo Ma <begeekmyfriend@gmail.com>
parent 1f13351a
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -11,6 +11,9 @@ import android.util.Log;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.IllegalFormatCodePointException;
import java.util.IllegalFormatException;
import java.util.IllegalFormatWidthException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
Loading
Loading
@@ -58,8 +61,6 @@ public class SrsEncoder {
private int videoMp4Track;
private int audioFlvTrack;
private int audioMp4Track;
private ByteBuffer outputYuvFrame = ByteBuffer.allocateDirect(VOUT_WIDTH * VOUT_HEIGHT * 3 / 2);
private Thread yuvPreprocessThread = null;
private ConcurrentLinkedQueue<byte[]> yuvQueue = new ConcurrentLinkedQueue<>();
Loading
Loading
@@ -90,7 +91,7 @@ public class SrsEncoder {
throw new IllegalStateException("Unsupported color format!");
}
setOutputResolution(outputYuvFrame, VOUT_WIDTH, VOUT_HEIGHT);
setOutputResolution(VOUT_WIDTH, VOUT_HEIGHT);
}
public int start() {
Loading
Loading
@@ -153,12 +154,14 @@ public class SrsEncoder {
while (!Thread.interrupted()) {
while (!yuvQueue.isEmpty()) {
byte[] data = yuvQueue.poll();
if (mOrientation == Configuration.ORIENTATION_PORTRAIT) {
portraitPreprocessYuvFrame(data);
byte[] processedData = mOrientation == Configuration.ORIENTATION_PORTRAIT ?
portraitPreprocessYuvFrame(data) : landscapePreprocessYuvFrame(data);
if (processedData != null) {
onProcessedYuvFrame(processedData);
} else {
landscapePreprocessYuvFrame(data);
Thread.getDefaultUncaughtExceptionHandler().uncaughtException(Thread.currentThread(),
new IllegalArgumentException("libyuv failure"));
}
onoutputYuvFrame();
}
// Wait for next yuv
synchronized (yuvLock) {
Loading
Loading
@@ -222,10 +225,10 @@ public class SrsEncoder {
vOutWidth = VOUT_HEIGHT;
vOutHeight = VOUT_WIDTH;
}
setOutputResolution(outputYuvFrame, vOutWidth, vOutHeight);
setOutputResolution(vOutWidth, vOutHeight);
}
private void onoutputYuvFrame() {
private void onProcessedYuvFrame(byte[] yuvFrame) {
ByteBuffer[] inBuffers = vencoder.getInputBuffers();
ByteBuffer[] outBuffers = vencoder.getOutputBuffers();
Loading
Loading
@@ -233,9 +236,9 @@ public class SrsEncoder {
if (inBufferIndex >= 0) {
ByteBuffer bb = inBuffers[inBufferIndex];
bb.clear();
bb.put(outputYuvFrame.array(), 0, outputYuvFrame.array().length);
bb.put(yuvFrame, 0, yuvFrame.length);
long pts = System.nanoTime() / 1000 - mPresentTimeUs;
vencoder.queueInputBuffer(inBufferIndex, 0, outputYuvFrame.array().length, pts, 0);
vencoder.queueInputBuffer(inBufferIndex, 0, yuvFrame.length, pts, 0);
}
for (; ; ) {
Loading
Loading
@@ -317,52 +320,44 @@ public class SrsEncoder {
}
}
private void portraitPreprocessYuvFrame(byte[] data) {
private byte[] portraitPreprocessYuvFrame(byte[] data) {
if (mCameraFaceFront) {
switch (mVideoColorFormat) {
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
NV21ToI420(data, VPREV_WIDTH, VPREV_HEIGHT, true, 270);
break;
return NV21ToI420(data, VPREV_WIDTH, VPREV_HEIGHT, true, 270);
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
NV21ToNV12(data, VPREV_WIDTH, VPREV_HEIGHT, true, 270);
break;
return NV21ToNV12(data, VPREV_WIDTH, VPREV_HEIGHT, true, 270);
default:
throw new IllegalStateException("Unsupported color format!");
}
} else {
switch (mVideoColorFormat) {
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
NV21ToI420(data, VPREV_WIDTH, VPREV_HEIGHT, false, 90);
break;
return NV21ToI420(data, VPREV_WIDTH, VPREV_HEIGHT, false, 90);
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
NV21ToNV12(data, VPREV_WIDTH, VPREV_HEIGHT, false, 90);
break;
return NV21ToNV12(data, VPREV_WIDTH, VPREV_HEIGHT, false, 90);
default:
throw new IllegalStateException("Unsupported color format!");
}
}
}
private void landscapePreprocessYuvFrame(byte[] data) {
private byte[] landscapePreprocessYuvFrame(byte[] data) {
if (mCameraFaceFront) {
switch (mVideoColorFormat) {
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
NV21ToI420(data, VPREV_WIDTH, VPREV_HEIGHT, true, 0);
break;
return NV21ToI420(data, VPREV_WIDTH, VPREV_HEIGHT, true, 0);
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
NV21ToNV12(data, VPREV_WIDTH, VPREV_HEIGHT, true, 0);
break;
return NV21ToNV12(data, VPREV_WIDTH, VPREV_HEIGHT, true, 0);
default:
throw new IllegalStateException("Unsupported color format!");
}
} else {
switch (mVideoColorFormat) {
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
NV21ToI420(data, VPREV_WIDTH, VPREV_HEIGHT, false, 0);
break;
return NV21ToI420(data, VPREV_WIDTH, VPREV_HEIGHT, false, 0);
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
NV21ToNV12(data, VPREV_WIDTH, VPREV_HEIGHT, false, 0);
break;
return NV21ToNV12(data, VPREV_WIDTH, VPREV_HEIGHT, false, 0);
default:
throw new IllegalStateException("Unsupported color format!");
}
Loading
Loading
@@ -430,9 +425,9 @@ public class SrsEncoder {
return matchedColorFormat;
}
private native void setOutputResolution(Object outputFrame, int outWidth, int outHeight);
private native int NV21ToI420(byte[] yuvFrame, int width, int height, boolean flip, int rotate);
private native int NV21ToNV12(byte[] yuvFrame, int width, int height, boolean flip, int rotate);
private native void setOutputResolution(int outWidth, int outHeight);
private native byte[] NV21ToI420(byte[] yuvFrame, int width, int height, boolean flip, int rotate);
private native byte[] NV21ToNV12(byte[] yuvFrame, int width, int height, boolean flip, int rotate);
static {
System.loadLibrary("yuv");
Loading
Loading
No preview for this file type
Loading
Loading
@@ -26,7 +26,7 @@ static struct YuvFrame i420_rotated_frame;
static struct YuvFrame i420_scaled_frame;
static struct YuvFrame output_frame;
static void libyuv_setOutputResolution(JNIEnv* env, jobject thiz, jobject output_buffer, jint out_width, jint out_height) {
static void libyuv_setOutputResolution(JNIEnv* env, jobject thiz, jint out_width, jint out_height) {
int y_size = out_width * out_height;
if (i420_scaled_frame.width != out_width || i420_scaled_frame.height != out_height) {
Loading
Loading
@@ -39,17 +39,19 @@ static void libyuv_setOutputResolution(JNIEnv* env, jobject thiz, jobject output
i420_scaled_frame.v = i420_scaled_frame.u + y_size / 4;
}
// Shared memory
output_frame.data = (uint8_t *)env->GetDirectBufferAddress(output_buffer);
output_frame.y = output_frame.data;
output_frame.u = output_frame.y + y_size;
output_frame.v = output_frame.u + y_size / 4;
output_frame.width = out_width;
output_frame.height = out_height;
if (output_frame.width != out_width || output_frame.height != out_height) {
free(output_frame.data);
output_frame.width = out_width;
output_frame.height = out_height;
output_frame.data = (uint8_t *) malloc(out_width * out_height * 3 / 2);
output_frame.y = output_frame.data;
output_frame.u = output_frame.y + y_size;
output_frame.v = output_frame.u + y_size / 4;
}
}
// For COLOR_FormatYUV420Planar
static jint libyuv_NV21ToI420(JNIEnv* env, jobject thiz, jbyteArray frame, jint src_width, jint src_height,
static jbyteArray libyuv_NV21ToI420(JNIEnv* env, jobject thiz, jbyteArray frame, jint src_width, jint src_height,
jboolean need_flip, jint rotate_degree) {
int y_size = src_width * src_height;
jbyte* input_frame = env->GetByteArrayElements(frame, NULL);
Loading
Loading
@@ -86,7 +88,7 @@ static jint libyuv_NV21ToI420(JNIEnv* env, jobject thiz, jbyteArray frame, jint
(RotationMode) rotate_degree, FOURCC_NV21);
if (ret < 0) {
LIBYUV_LOGE("ConvertToI420 failure");
return JNI_ERR;
return NULL;
}
ret = I420Scale(i420_rotated_frame.y, i420_rotated_frame.width,
Loading
Loading
@@ -100,15 +102,19 @@ static jint libyuv_NV21ToI420(JNIEnv* env, jobject thiz, jbyteArray frame, jint
kFilterNone);
if (ret < 0) {
LIBYUV_LOGE("I420Scale failure");
return JNI_ERR;
return NULL;
}
y_size = output_frame.width * output_frame.height;
jbyteArray outputFrame = env->NewByteArray(y_size * 3 / 2);
env->SetByteArrayRegion(outputFrame, 0, y_size * 3 / 2, (jbyte *) output_frame.data);
env->ReleaseByteArrayElements(frame, input_frame, JNI_ABORT);
return JNI_OK;
return outputFrame;
}
// For COLOR_FormatYUV420SemiPlanar
static jint libyuv_NV21ToNV12(JNIEnv* env, jobject thiz, jbyteArray frame, jint src_width, jint src_height,
static jbyteArray libyuv_NV21ToNV12(JNIEnv* env, jobject thiz, jbyteArray frame, jint src_width, jint src_height,
jboolean need_flip, jint rotate_degree) {
int y_size = src_width * src_height;
jbyte* input_frame = env->GetByteArrayElements(frame, NULL);
Loading
Loading
@@ -145,7 +151,7 @@ static jint libyuv_NV21ToNV12(JNIEnv* env, jobject thiz, jbyteArray frame, jint
(RotationMode) rotate_degree, FOURCC_NV21);
if (ret < 0) {
LIBYUV_LOGE("ConvertToI420 failure");
return JNI_ERR;
return NULL;
}
ret = I420Scale(i420_rotated_frame.y, i420_rotated_frame.width,
Loading
Loading
@@ -159,7 +165,7 @@ static jint libyuv_NV21ToNV12(JNIEnv* env, jobject thiz, jbyteArray frame, jint
kFilterNone);
if (ret < 0) {
LIBYUV_LOGE("I420Scale failure");
return JNI_ERR;
return NULL;
}
ret = ConvertFromI420(i420_scaled_frame.y, i420_scaled_frame.width,
Loading
Loading
@@ -170,17 +176,21 @@ static jint libyuv_NV21ToNV12(JNIEnv* env, jobject thiz, jbyteArray frame, jint
FOURCC_NV12);
if (ret < 0) {
LIBYUV_LOGE("ConvertFromI420 failure");
return JNI_ERR;
return NULL;
}
y_size = output_frame.width * output_frame.height;
jbyteArray outputFrame = env->NewByteArray(y_size * 3 / 2);
env->SetByteArrayRegion(outputFrame, 0, y_size * 3 / 2, (jbyte *) output_frame.data);
env->ReleaseByteArrayElements(frame, input_frame, JNI_ABORT);
return JNI_OK;
return outputFrame;
}
static JNINativeMethod libyuv_methods[] = {
{ "setOutputResolution", "(Ljava/lang/Object;II)V", (void *)libyuv_setOutputResolution },
{ "NV21ToI420", "([BIIZI)I", (void *)libyuv_NV21ToI420 },
{ "NV21ToNV12", "([BIIZI)I", (void *)libyuv_NV21ToNV12 },
{ "setOutputResolution", "(II)V", (void *)libyuv_setOutputResolution },
{ "NV21ToI420", "([BIIZI)[B", (void *)libyuv_NV21ToI420 },
{ "NV21ToNV12", "([BIIZI)[B", (void *)libyuv_NV21ToNV12 },
};
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment