Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

多次调用YuvUtil.compressYUV程序闪退 #4

Open
TIME1992 opened this issue Jan 17, 2019 · 6 comments
Open

多次调用YuvUtil.compressYUV程序闪退 #4

TIME1992 opened this issue Jan 17, 2019 · 6 comments

Comments

@TIME1992
Copy link

for (int i = 0; i < 10000; i++) {
byte[] out=new byte[640*480];
YuvUtil.compressYUV(data,1920,1080,out,640,480,0,0,false);
}
如题,多次调用compressYUV程序闪退,无错误日志,是c层有空指针了吗

@hzl123456
Copy link
Owner

oom了,,,demo中的例子compressYUV方法没有对中间操作产生的数据进行释放操作

@TIME1992
Copy link
Author

方便优化一下吗?觉得您写的库蛮好用的,有oom蛮可惜的

@hzl123456
Copy link
Owner

这只是个demo,介绍libyuv的一些常用的方法,对于自己的项目中要使用的话,可以自己修改下。
如果yuv的原始数据的宽高都一致的话,可以在c层只进行一次的空间分配,所有操作结束后再进行释放

@TIME1992
Copy link
Author

好的,非常感谢!

@DavidBei
Copy link

有内存泄漏的问题,两个地方,一个是compressYUV中的init方法中的mlloc出来的三个数组,一个是新建的Src_data数组。
我是需要每一帧数据都要处理,所以很容易发生这个问题,我的修改如下,如有不对,请大家指正:
extern "C"
JNIEXPORT void JNICALL
Java_com_ecarx_yuvlib_YuvUtil_compressYUV(JNIEnv *env, jclass type,
jbyteArray src_, jint width,
jint height, jbyteArray dst_,
jint dst_width, jint dst_height,
jint mode, jint degree,
jboolean isMirror) {
//为中间操作需要的分配空间
// init(width, height, dst_width, dst_height);
jbyte *Src_i420_data;
jbyte *Src_i420_data_scale;
jbyte *Src_i420_data_rotate;

Src_i420_data = (jbyte *) malloc(sizeof(jbyte) * width * height * 3 / 2);
Src_i420_data_scale = (jbyte *) malloc(sizeof(jbyte) * dst_width * dst_height * 3 / 2);
Src_i420_data_rotate = (jbyte *) malloc(sizeof(jbyte) * dst_width * dst_height * 3 / 2);

jbyte *Src_data = env->GetByteArrayElements(src_, NULL);
jbyte *Dst_data = env->GetByteArrayElements(dst_, NULL);
//nv21转化为i420

// nv21ToI420(Src_data, width, height, Src_i420_data);
//进行缩放的操作
scaleI420(Src_data, width, height, Dst_data, dst_width, dst_height, mode);

// if (isMirror) {
// //进行旋转的操作
// rotateI420(Src_i420_data_scale, dst_width, dst_height, Src_i420_data_rotate, degree);
// //因为旋转的角度都是90和270,那后面的数据width和height是相反的
// mirrorI420(Src_i420_data_rotate, dst_height, dst_width, Dst_data);
// } else {
// rotateI420(Src_i420_data_scale, dst_width, dst_height, Dst_data, degree);
// }

free(Src_i420_data);
free(Src_i420_data_scale);
free(Src_i420_data_rotate);

env->ReleaseByteArrayElements(src_, Src_data, 0);
env->ReleaseByteArrayElements(dst_, Dst_data, 0);

}

另外两个方法也是有同样的第二个问题,也增加了两句释放的代码:

extern "C"
JNIEXPORT void JNICALL
Java_com_ecarx_yuvlib_YuvUtil_cropYUV(JNIEnv *env, jclass type, jbyteArray src_, jint width,
jint height, jbyteArray dst_, jint dst_width, jint dst_height,
jint left, jint top) {
//裁剪的区域大小不对
if (left + dst_width > width || top + dst_height > height) {
return;
}

//left和top必须为偶数,否则显示会有问题
if (left % 2 != 0 || top % 2 != 0) {
    return;
}

jint src_length = env->GetArrayLength(src_);
jbyte *src_i420_data = env->GetByteArrayElements(src_, NULL);
jbyte *dst_i420_data = env->GetByteArrayElements(dst_, NULL);


jint dst_i420_y_size = dst_width * dst_height;
jint dst_i420_u_size = (dst_width >> 1) * (dst_height >> 1);

jbyte *dst_i420_y_data = dst_i420_data;
jbyte *dst_i420_u_data = dst_i420_data + dst_i420_y_size;
jbyte *dst_i420_v_data = dst_i420_data + dst_i420_y_size + dst_i420_u_size;

libyuv::ConvertToI420((const uint8 *) src_i420_data, src_length,
                      (uint8 *) dst_i420_y_data, dst_width,
                      (uint8 *) dst_i420_u_data, dst_width >> 1,
                      (uint8 *) dst_i420_v_data, dst_width >> 1,
                      left, top,
                      width, height,
                      dst_width, dst_height,
                      libyuv::kRotate0, libyuv::FOURCC_I420);

env->ReleaseByteArrayElements(src_, src_i420_data, 0);
env->ReleaseByteArrayElements(dst_, dst_i420_data, 0);

}

extern "C"
JNIEXPORT void JNICALL
Java_com_ecarx_yuvlib_YuvUtil_yuvI420ToNV21(JNIEnv *env, jclass type, jbyteArray i420Src,
jbyteArray nv21Src,
jint width, jint height) {

jbyte *src_i420_data = env->GetByteArrayElements(i420Src, NULL);
jbyte *src_nv21_data = env->GetByteArrayElements(nv21Src, NULL);

jint src_y_size = width * height;
jint src_u_size = (width >> 1) * (height >> 1);

jbyte *src_i420_y_data = src_i420_data;
jbyte *src_i420_u_data = src_i420_data + src_y_size;
jbyte *src_i420_v_data = src_i420_data + src_y_size + src_u_size;

jbyte *src_nv21_y_data = src_nv21_data;
jbyte *src_nv21_vu_data = src_nv21_data + src_y_size;



libyuv::I420ToNV21(
        (const uint8 *) src_i420_y_data, width,
        (const uint8 *) src_i420_u_data, width >> 1,
        (const uint8 *) src_i420_v_data, width >> 1,
        (uint8 *) src_nv21_y_data, width,
        (uint8 *) src_nv21_vu_data, width,
        width, height);

env->ReleaseByteArrayElements(i420Src, src_i420_data, 0);
env->ReleaseByteArrayElements(nv21Src, src_nv21_data, 0);

}

@hzl123456
Copy link
Owner

可以为 init(width, height, dst_width, dst_height); 写一个javaCallC的方法,,,然后如果只执行一次 init 的话就可以了,如果输入输出宽高有变化的话再重新执行 init

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants