实现 libYUV打包编译成so文件,并实现NV21转yuv420转码操作

实现 libYUV打包编译成so文件,并实现NV21转yuv420转码操作

  • 1.打包libyuv.so
  • 2.实现JNI编写,实现NV21转yuv420,镜像处理,角度旋转
  • 3.测试,优化性能,降低cpu性能5%左右

1.下载libyuv源码,打包libyuv.so文件,mk文件如下:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := \
    source/compare.cc           \
    source/compare_common.cc    \
    source/compare_neon.cc  \
    source/compare_neon64.cc   \
    source/compare_posix.cc  \
    source/compare_win.cc   \
    source/convert.cc  \
    source/convert_argb.cc  \
    source/convert_from.cc  \
    source/convert_from_argb.cc  \
    source/convert_jpeg.cc  \
    source/convert_to_argb.cc   \
    source/convert_to_i420.cc  \
    source/cpu_id.cc  \
    source/format_conversion.cc  \
    source/mjpeg_decoder.cc  \
    source/mjpeg_validate.cc  \
    source/planar_functions.cc  \
    source/rotate.cc  \
    source/rotate_argb.cc  \
    source/rotate_mips.cc  \
    source/rotate_neon.cc   \
    source/rotate_neon64.cc  \
    source/row_any.cc  \
    source/row_common.cc  \
    source/row_mips.cc  \
    source/row_neon.cc  \
    source/row_neon64.cc  \
    source/row_posix.cc  \
    source/row_win.cc  \
    source/row_x86.asm  \
    source/scale.cc   \
    source/scale_argb.cc  \
    source/scale_common.cc  \
    source/scale_mips.cc  \
    source/scale_neon.cc  \
    source/scale_neon64.cc  \
    source/scale_posix.cc  \
    source/scale_win.cc  \
    source/video_common.cc  \
    OpenCVHelper.cpp \
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_MODULE := libyuv
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)

执行:ndk-build 生成 libyuv.so文件


2.调用libyuv中的方法实现NV21转yuv420,镜像,角度旋转代码实现:

int VideoStreamProcess(unsigned char *Src_data, unsigned char *Dst_data,
                       int src_width, int src_height,
                       bool EnableRotate, bool EnableMirror,
                       unsigned char *Dst_data_mirror, unsigned char *Dst_data_rotate,
                       int rotatemodel) {
    //src:NV12 video size
    int NV12_Size = src_width * src_height * 3 / 2;
    int NV12_Y_Size = src_width * src_height;

    //dst:YUV420 video size
    int I420_Size = src_width * src_height * 3 / 2;
    int I420_Y_Size = src_width * src_height;
    int I420_U_Size = (src_width >> 1) * (src_height >> 1);
    int I420_V_Size = I420_U_Size;

    // video format transformation process
    unsigned char *Y_data_Src = Src_data;
    unsigned char *UV_data_Src = Src_data + NV12_Y_Size;
    int src_stride_y = src_width;
    int src_stride_uv = src_width;

    unsigned char *Y_data_Dst = Dst_data;
    unsigned char *U_data_Dst = Dst_data + I420_Y_Size;
    unsigned char *V_data_Dst = Dst_data + I420_Y_Size + I420_U_Size;

    int Dst_Stride_Y = src_width;
    int Dst_Stride_U = src_width >> 1;
    int Dst_Stride_V = Dst_Stride_U;
//NV12ToI420
    libyuv::NV21ToI420(Y_data_Src, src_stride_y,
                       UV_data_Src, src_stride_uv,
                       Y_data_Dst, Dst_Stride_Y,
                       U_data_Dst, Dst_Stride_U,
                       V_data_Dst, Dst_Stride_V,
                       src_width, src_height);




    // video mirror process
    unsigned char *Y_data_Dst_mirror = Dst_data_mirror;
    unsigned char *U_data_Dst_mirror = Dst_data_mirror + I420_Y_Size;
    unsigned char *V_data_Dst_mirror = Dst_data_mirror + I420_Y_Size + I420_U_Size;
    int Dst_Stride_Y_mirror = src_width;
    int Dst_Stride_U_mirror = src_width >> 1;
    int Dst_Stride_V_mirror = Dst_Stride_U_mirror;

    if (EnableMirror) {
        libyuv::I420Mirror(Y_data_Dst, Dst_Stride_Y,
                           U_data_Dst, Dst_Stride_U,
                           V_data_Dst, Dst_Stride_V,
                           Y_data_Dst_mirror, Dst_Stride_Y_mirror,
                           U_data_Dst_mirror, Dst_Stride_U_mirror,
                           V_data_Dst_mirror, Dst_Stride_V_mirror,
                           src_width, src_height);
    }

    //video rotate process
    if (EnableRotate) {
        int Dst_Stride_Y_rotate;
        int Dst_Stride_U_rotate;
        int Dst_Stride_V_rotate;
        unsigned char *Y_data_Dst_rotate = Dst_data_rotate;
        unsigned char *U_data_Dst_rotate = Dst_data_rotate + I420_Y_Size;
        unsigned char *V_data_Dst_rotate = Dst_data_rotate + I420_Y_Size + I420_U_Size;

        if (rotatemodel == libyuv::kRotate90 || rotatemodel == libyuv::kRotate270) {
            Dst_Stride_Y_rotate = src_height;
            Dst_Stride_U_rotate = src_height >> 1;
            Dst_Stride_V_rotate = Dst_Stride_U_rotate;
        }
        else {
            Dst_Stride_Y_rotate = src_width;
            Dst_Stride_U_rotate = src_width >> 1;
            Dst_Stride_V_rotate = Dst_Stride_U_rotate;
        }

        if (EnableMirror) {
            libyuv::I420Rotate(Y_data_Dst_mirror, Dst_Stride_Y_mirror,
                               U_data_Dst_mirror, Dst_Stride_U_mirror,
                               V_data_Dst_mirror, Dst_Stride_V_mirror,
                               Y_data_Dst_rotate, Dst_Stride_Y_rotate,
                               U_data_Dst_rotate, Dst_Stride_U_rotate,
                               V_data_Dst_rotate, Dst_Stride_V_rotate,
                               src_width, src_height,
                               (libyuv::RotationMode) rotatemodel);
        }
        else {
            libyuv::I420Rotate(Y_data_Dst, Dst_Stride_Y,
                               U_data_Dst, Dst_Stride_U,
                               V_data_Dst, Dst_Stride_V,
                               Y_data_Dst_rotate, Dst_Stride_Y_rotate,
                               U_data_Dst_rotate, Dst_Stride_U_rotate,
                               V_data_Dst_rotate, Dst_Stride_V_rotate,
                               src_width, src_height,
                               (libyuv::RotationMode) rotatemodel);
        }
    }
    return 0;
}

3.测试调用

@Override
    public void onPreviewFrame(byte[] data, Camera callbackCamera) {
        if (mCamera == null || !CameraInterface.getInstance().isOpenCamera() || mCamera != callbackCamera) {
            return;
        }
        try {
            int rotation = 0;
            if (myOrientationDetector != null)
                rotation = myOrientationDetector.getRotation();
            cameraType = CameraInterface.getInstance().getCameraType();
            //调用libYuv,转yuv420并旋转270度
           byte[] rotaeData = CodeUtil.getInstance().nv21To420(data, mCaptureWidth, mCaptureHeight, 270, false, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        mCamera.addCallbackBuffer(data);
    }

4.测试结果比较(同一个时间段)

图一: 使用libyuv,转码旋转270度的cpu使用情况

这里写图片描述

图二:使用普通的算法,转码旋转270度的cpu使用情况

这里写图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ada

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值