目录

一、下拉google官方的libyuv库代码

二、在android项目中集成libyuv库

1.环境配置

2.拷贝libyuv源码文件

​编辑3.配置cmake libyuv相关的链接编译等

三、使用libyuv库

1.libyuv库完成camera的旋转

2.libyuv库实现翻转

3.libyuv库实现缩放

4.libyuv库实现裁剪


一、下拉google官方的libyuv库代码

官方地址 https://chromium.googlesource.com/libyuv/libyuv

如果打不开打不开,可以去 github 上下载:https://github.com/lemenkov/libyuv

下拉完成后目录如下所示:

主要我们用到的是include和source目录内容

二、在android项目中集成libyuv库

1.环境配置

首先配置方面要支持ndk,所以需要下载cmake和ndk配置,如下:

然后下面的集成流程是根据Android Studio Electric Eel | 2022.1.1 Patch 2版本进行的,不同版本可以稍有差异

2.拷贝libyuv源码文件

将include的文件和source文件拷贝到项目中,我这边是专门在cpp目录下建了一个libyuv文件夹,然后将include文件夹和source文件夹拷贝进来,如下:


3.配置cmake libyuv相关的链接编译等

首先我的cmake路径和libyuv是在同一目录下,这个老版本android studio和新版本有所差异,注意分辨,和下面的cmake中配置libyuv路径有关,然后我这边是以同一目录下进行配置的,配置文件如下所示:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html# Sets the minimum version of CMake required to build the native library.cmake_minimum_required(VERSION 3.6.0)# Declares and names the project.project("xxx")# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.set(baseCppPath "libyuv")SET(ly_src_dir ${baseCppPath})
FILE(GLOB_RECURSE ly_source_files ${ly_src_dir}/*.cc)
LIST(SORT ly_source_files)add_library( # Sets the name of the library.liveassistant# Sets the library as a shared library.SHARED# Provides a relative path to your source file(s).${ly_source_files}native-lib.cpp)include_directories(${baseCppPath}/include)# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.find_library( # Sets the name of the path variable.log-lib# Specifies the name of the NDK library that# you want CMake to locate.log)# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.target_link_libraries( # Specifies the target library.xxx# Links the target library to the log library# included in the NDK.jnigraphics${log-lib})如果想详细了解上面cmake配置的具体内容可参考:https://gonglipeng.blog.csdn.net/article/details/120026867

三、使用libyuv库

1.libyuv库完成camera的旋转

首先在jni中的cpp文件中添加头文件,如下:

头文件

#include <jni.h>

#include <string>

#include <libyuv.h>

#include <android/bitmap.h>

然后是cpp文件的具体实现

extern "C"

JNIEXPORT void JNICALL

Java_xxx_xxx_xxx_xxx_YuvNativeUtil_rotate(JNIEnv *env, jclass thiz, jobject y,

                                                          jobject u,

                                                          jobject v, jint yStride, jint uStride,

                                                          jint vStride,

                                                          jobject yOut, jobject uOut, jobject vOut,

                                                          jint yOutStride, jint uOutStride,

                                                          jint vOutStride,

                                                          jint width, jint height,

                                                          jint rotationMode) {

    uint8_t *yNative = (uint8_t *) env->GetDirectBufferAddress(y);

    uint8_t *uNative = (uint8_t *) env->GetDirectBufferAddress(u);

    uint8_t *vNative = (uint8_t *) env->GetDirectBufferAddress(v);

    uint8_t *yOutNative = (uint8_t *) env->GetDirectBufferAddress(yOut);

    uint8_t *uOutNative = (uint8_t *) env->GetDirectBufferAddress(uOut);

    uint8_t *vOutNative = (uint8_t *) env->GetDirectBufferAddress(vOut);

    libyuv::I420Rotate(yNative, yStride,

                       uNative, uStride,

                       vNative, vStride,

                       yOutNative, yOutStride,

                       uOutNative, uOutStride,

                       vOutNative, vOutStride,

                       width, height,

                       libyuv::RotationMode(rotationMode));

}

上面xxx对应自己的路径名

然后是java层代码实现,先加载so包:

static {

        System.loadLibrary("xxx");

    }

然后实现java代码,如下:

   public static YuvFrame rotate(Image image, int rotationMode) {

       YuvFrame outFrame = FramesFactory.INSTANCE.instanceYuv(image.getWidth(),

               image.getHeight(), rotationMode);

       rotate(image.getPlanes()[0].getBuffer(),

               image.getPlanes()[1].getBuffer(),

               image.getPlanes()[2].getBuffer(),

               image.getPlanes()[0].getRowStride(),

               image.getPlanes()[1].getRowStride(),

               image.getPlanes()[2].getRowStride(),

               outFrame.getY(),

               outFrame.getU(),

               outFrame.getV(),

               outFrame.getYStride(),

               outFrame.getUStride(),

               outFrame.getVStride(),

               image.getWidth(),

               image.getHeight(),

               rotationMode);

       return outFrame;

   }

   public static YuvFrame rotate(YuvFrame yuvFrame, int rotationMode) {

       YuvFrame outFrame = FramesFactory.INSTANCE.instanceYuv(yuvFrame.getWidth(),

               yuvFrame.getHeight(), rotationMode);

       rotate(yuvFrame.getY(),

               yuvFrame.getU(),

               yuvFrame.getV(),

               yuvFrame.getYStride(),

               yuvFrame.getUStride(),

               yuvFrame.getVStride(),

               outFrame.getY(),

               outFrame.getU(),

               outFrame.getV(),

               outFrame.getYStride(),

               outFrame.getUStride(),

               outFrame.getVStride(),

               yuvFrame.getWidth(),

               yuvFrame.getHeight(),

               rotationMode);

       return outFrame;

   }

   private static native void rotate(ByteBuffer y,

                                     ByteBuffer u,

                                     ByteBuffer v,

                                     int yStride,

                                     int uStride,

                                     int vStride,

                                     ByteBuffer yOut,

                                     ByteBuffer uOut,

                                     ByteBuffer vOut,

                                     int yOutStride,

                                     int uOutStride,

                                     int vOutStride,

                                     int width,

                                     int height,

                                     int rotationMode);

上面两种实现一是直接传入camera2中通过OnImageAvailableListener回调获取的Image,部分代码如下:

另一种方式是传递中间数据YuvFrame,然后写存储数据的YuvFrame类,如下,注意是kotlin方式写的

class YuvFrame {

    lateinit var y: ByteBuffer; private set

    lateinit var u: ByteBuffer; private set

    lateinit var v: ByteBuffer; private set

    var yStride: Int = 0private set

    var uStride: Int = 0private set

    var vStride: Int = 0private set

    var width: Int = 0private set

    var height: Int = 0private set

    fun fill(

        y: ByteBuffer,

        u: ByteBuffer,

        v: ByteBuffer,

        yStride: Int,

        uStride: Int,

        vStride: Int,

        width: Int,

        height: Int

    ) {

        this.y = y

        this.u = u

        this.v = v

        this.yStride = yStride

        this.uStride = uStride

        this.vStride = vStride

        this.width = width

        this.height = height

    }

    fun fill(image: Image) {

        for (i in 0 until 3) {

            when (i) {

                0 -> {

                    y = image.planes[i].buffer

                    yStride = image.planes[i].rowStride

                }

                1 -> {

                    u = image.planes[i].buffer

                    uStride = image.planes[i].rowStride

                }

                2 -> {

                    v = image.planes[i].buffer

                    vStride = image.planes[i].rowStride

                }

            }

        }

        width = image.width

        height = image.height

    }

    /** experimental method */

    fun fill(width: Int, height: Int, data: ByteArray) {

        this.width = width

        this.height = height

        val yArr = ByteArray(width * height)

        val uArr = ByteArray(width * height / 4)

        val vArr = ByteArray(width * height / 4)

        System.arraycopy(data, 0, yArr, 0, yArr.size)

        System.arraycopy(data, yArr.size, uArr, 0, uArr.size)

        System.arraycopy(data, yArr.size + uArr.size, vArr, 0, uArr.size)

        y = ByteBuffer.allocateDirect(yArr.size).put(yArr)

        u = ByteBuffer.allocateDirect(uArr.size).put(uArr)

        v = ByteBuffer.allocateDirect(vArr.size).put(vArr)

        y.position(0)

        u.position(0)

        v.position(0)

    }

    fun asArray(): ByteArray {

        var array: ByteArray

        val yPos = y.position()

        val uPos = u.position()

        val vPos = v.position()

        try {

            array =

                ByteBuffer.allocate(y.capacity() + u.capacity() + v.capacity()).put(y).put(u).put(v)

                    .array()

            y.position(yPos)

            u.position(uPos)

            v.position(vPos)

        catch (e: Exception) {

            array = ByteArray(size())

            y.get(array, 0, y.remaining())

            y.position(yPos)

            u.get(array, y.remaining(), u.remaining())

            u.position(uPos)

            v.get(array, y.remaining() + u.remaining(), v.remaining())

            v.position(vPos)

        }

        return array

    }

    fun size() = y.remaining() + u.remaining() + v.remaining()

    fun free() {

        y = ByteBuffer.allocate(1)

        u = ByteBuffer.allocate(1)

        v = ByteBuffer.allocate(1)

        yStride = 0

        uStride = 0

        vStride = 0

        width = 0

        height = 0

    }

}

2.libyuv库实现翻转

翻转有水平翻转和垂直翻转,垂直翻转可以直接通过旋转实现,水平翻转需要重新调用libyuv库,代码如下所示:

extern "C"

JNIEXPORT void JNICALL

Java_xxx_xxx_xxx_utils_YuvNativeUtil_mirrorH(JNIEnv *env, jclass thiz, jobject y,

                                                           jobject u,

                                                           jobject v, jint yStride, jint uStride,

                                                           jint vStride,

                                                           jobject yOut, jobject uOut, jobject vOut,

                                                           jint yOutStride, jint uOutStride,

                                                           jint vOutStride,

                                                           jint width, jint height) {

    uint8_t *yNative = (uint8_t *) env->GetDirectBufferAddress(y);

    uint8_t *uNative = (uint8_t *) env->GetDirectBufferAddress(u);

    uint8_t *vNative = (uint8_t *) env->GetDirectBufferAddress(v);

    uint8_t *yOutNative = (uint8_t *) env->GetDirectBufferAddress(yOut);

    uint8_t *uOutNative = (uint8_t *) env->GetDirectBufferAddress(uOut);

    uint8_t *vOutNative = (uint8_t *) env->GetDirectBufferAddress(vOut);

    libyuv::I420Mirror(yNative, yStride,

                       uNative, uStride,

                       vNative, vStride,

                       yOutNative, yOutStride,

                       uOutNative, uOutStride,

                       vOutNative, vOutStride,

                       width, height);

}

public static YuvFrame mirrorH(Image image) {

        YuvFrame outFrame = FramesFactory.INSTANCE.instanceYuv(image.getWidth(), image.getHeight());

        mirrorH(image.getPlanes()[0].getBuffer(),

                image.getPlanes()[1].getBuffer(),

                image.getPlanes()[2].getBuffer(),

                image.getPlanes()[0].getRowStride(),

                image.getPlanes()[1].getRowStride(),

                image.getPlanes()[2].getRowStride(),

                outFrame.getY(),

                outFrame.getU(),

                outFrame.getV(),

                outFrame.getYStride(),

                outFrame.getUStride(),

                outFrame.getVStride(),

                image.getWidth(),

                image.getHeight());

        return outFrame;

    }

    public static YuvFrame mirrorH(YuvFrame yuvFrame) {

        YuvFrame outFrame = FramesFactory.INSTANCE.instanceYuv(yuvFrame.getWidth(),

                yuvFrame.getHeight());

        mirrorH(yuvFrame.getY(),

                yuvFrame.getU(),

                yuvFrame.getV(),

                yuvFrame.getYStride(),

                yuvFrame.getUStride(),

                yuvFrame.getVStride(),

                outFrame.getY(),

                outFrame.getU(),

                outFrame.getV(),

                outFrame.getYStride(),

                outFrame.getUStride(),

                outFrame.getVStride(),

                yuvFrame.getWidth(),

                yuvFrame.getHeight());

        return outFrame;

    }

    public static YuvFrame mirrorV(Image image) {

        YuvFrame outFrame = FramesFactory.INSTANCE.instanceYuv(image.getWidth(), image.getHeight());

        rotate(image.getPlanes()[0].getBuffer(),

                image.getPlanes()[1].getBuffer(),

                image.getPlanes()[2].getBuffer(),

                image.getPlanes()[0].getRowStride(),

                image.getPlanes()[1].getRowStride(),

                image.getPlanes()[2].getRowStride(),

                outFrame.getY(),

                outFrame.getU(),

                outFrame.getV(),

                outFrame.getYStride(),

                outFrame.getUStride(),

                outFrame.getVStride(),

                image.getWidth(),

                -image.getHeight(),

                0);

        return outFrame;

    }

    public static YuvFrame mirrorV(YuvFrame yuvFrame) {

        YuvFrame outFrame = FramesFactory.INSTANCE.instanceYuv(yuvFrame.getWidth(),

                yuvFrame.getHeight());

        rotate(yuvFrame.getY(),

                yuvFrame.getU(),

                yuvFrame.getV(),

                yuvFrame.getYStride(),

                yuvFrame.getUStride(),

                yuvFrame.getVStride(),

                outFrame.getY(),

                outFrame.getU(),

                outFrame.getV(),

                outFrame.getYStride(),

                outFrame.getUStride(),

                outFrame.getVStride(),

                yuvFrame.getWidth(),

                -yuvFrame.getHeight(),

                0);

        return outFrame;

    }

    private static native void mirrorH(ByteBuffer y,

                                       ByteBuffer u,

                                       ByteBuffer v,

                                       int yStride,

                                       int uStride,

                                       int vStride,

                                       ByteBuffer yOut,

                                       ByteBuffer uOut,

                                       ByteBuffer vOut,

                                       int yOutStride,

                                       int uOutStride,

                                       int vOutStride,

                                       int width,

                                       int height);

3.libyuv库实现缩放

注意宽高必须为偶数,不然会出现花屏,代码如下所示:

extern "C"

JNIEXPORT void JNICALL

Java_xxx_xxx_xxx_utils_YuvNativeUtil_scale(

        JNIEnv *env, jclass thiz, jobject y, jobject u, jobject v,

        jint yStride, jint uStride, jint vStride,

        jobject yOut, jobject uOut, jobject vOut,

        jint yOutStride, jint uOutStride, jint vOutStride,

        jint srcWidth, jint srcHeight, jint dstWidth, jint dstHeight, jint filterMode) {

    uint8_t *yNative = (uint8_t *) env->GetDirectBufferAddress(y);

    uint8_t *uNative = (uint8_t *) env->GetDirectBufferAddress(u);

    uint8_t *vNative = (uint8_t *) env->GetDirectBufferAddress(v);

    uint8_t *yOutNative = (uint8_t *) env->GetDirectBufferAddress(yOut);

    uint8_t *uOutNative = (uint8_t *) env->GetDirectBufferAddress(uOut);

    uint8_t *vOutNative = (uint8_t *) env->GetDirectBufferAddress(vOut);

    libyuv::I420Scale(yNative, yStride,

                      uNative, uStride,

                      vNative, vStride,

                      srcWidth, srcHeight,

                      yOutNative, yOutStride,

                      uOutNative, uOutStride,

                      vOutNative, vOutStride,

                      dstWidth, dstHeight,

                      libyuv::FilterMode(filterMode));

}

public static YuvFrame scale(Image image, int dstWidth, int dstHeight, int filerMode) {

    YuvFrame outFrame = FramesFactory.INSTANCE.instanceYuv(dstWidth, dstHeight);

    scale(image.getPlanes()[0].getBuffer(),

            image.getPlanes()[1].getBuffer(),

            image.getPlanes()[2].getBuffer(),

            image.getPlanes()[0].getRowStride(),

            image.getPlanes()[1].getRowStride(),

            image.getPlanes()[2].getRowStride(),

            outFrame.getY(),

            outFrame.getU(),

            outFrame.getV(),

            outFrame.getYStride(),

            outFrame.getUStride(),

            outFrame.getVStride(),

            image.getWidth(),

            image.getHeight(),

            dstWidth,

            dstHeight,

            filerMode);

    return outFrame;

}

public static YuvFrame scale(YuvFrame yuvFrame, int dstWidth, int dstHeight, int filerMode) {

    if (dstHeight <= 0 || dstWidth <= 0) {

        return null;

    }

    YuvFrame outFrame = FramesFactory.INSTANCE.instanceYuv(dstWidth, dstHeight);

    scale(yuvFrame.getY(),

            yuvFrame.getU(),

            yuvFrame.getV(),

            yuvFrame.getYStride(),

            yuvFrame.getUStride(),

            yuvFrame.getVStride(),

            outFrame.getY(),

            outFrame.getU(),

            outFrame.getV(),

            outFrame.getYStride(),

            outFrame.getUStride(),

            outFrame.getVStride(),

            yuvFrame.getWidth(),

            yuvFrame.getHeight(),

            dstWidth,

            dstHeight,

            filerMode);

    return outFrame;

}

private static native void scale(ByteBuffer y,

                                 ByteBuffer u,

                                 ByteBuffer v,

                                 int yStride,

                                 int uStride,

                                 int vStride,

                                 ByteBuffer yOut,

                                 ByteBuffer uOut,

                                 ByteBuffer vOut,

                                 int yOutStride,

                                 int uOutStride,

                                 int vOutStride,

                                 int srcWidth,

                                 int srcHeight,

                                 int dstWidth,

                                 int dstHeight,

                                 int filterMode);

4.libyuv库实现裁剪

注意宽高和位置必须为偶数,不然会出现花屏,代码如下:

extern "C"

JNIEXPORT void JNICALL

Java_xxx_xxx_xxx_utils_YuvNativeUtil_crop(JNIEnv *env, jclass thiz, jbyteArray src_,

                                                        jobject yOut, jobject uOut, jobject vOut,

                                                        jint yOutStride, jint uOutStride,

                                                        jint vOutStride,

                                                        jint width, jint height, 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);

    uint8_t *yOutNative = (uint8_t *) env->GetDirectBufferAddress(yOut);

    uint8_t *uOutNative = (uint8_t *) env->GetDirectBufferAddress(uOut);

    uint8_t *vOutNative = (uint8_t *) env->GetDirectBufferAddress(vOut);

    libyuv::ConvertToI420((const uint8_t *) src_i420_data, width*height*3/2,

                          (uint8_t *) yOutNative, yOutStride,

                          (uint8_t *) uOutNative, uOutStride,

                          (uint8_t *) vOutNative, vOutStride,

                          left, top,

                          width, height,

                          dst_width, dst_height,

                          libyuv::kRotate0, libyuv::FOURCC_NV21);

}

/**

 * 裁剪,下面必须为偶数 不然画面会有问题

 *

 * @param src

 * @param image

 * @param cropWidth  必须为偶数

 * @param cropHeight 必须为偶数

 * @param left       必须为偶数

 * @param top        必须为偶数

 * @return

 */

public static YuvFrame crop(byte[] src, Image image, int cropWidth, int cropHeight, int left,

                            int top) {

    YuvFrame outFrame = FramesFactory.INSTANCE.instanceYuv(cropWidth, cropHeight);

    crop(src,

            outFrame.getY(),

            outFrame.getU(),

            outFrame.getV(),

            outFrame.getYStride(),

            outFrame.getUStride(),

            outFrame.getVStride(),

            image.getWidth(),

            image.getHeight(),

            outFrame.getWidth(),

            outFrame.getHeight(),

            left, top);

    return outFrame;

}

public static YuvFrame crop(byte[] src, YuvFrame yuvFrame, int cropWidth, int cropHeight,

                            int left,

                            int top) {

    YuvFrame outFrame = FramesFactory.INSTANCE.instanceYuv(cropWidth, cropHeight);

    crop(src,

            outFrame.getY(),

            outFrame.getU(),

            outFrame.getV(),

            outFrame.getYStride(),

            outFrame.getUStride(),

            outFrame.getVStride(),

            yuvFrame.getWidth(),

            yuvFrame.getHeight(),

            outFrame.getWidth(),

            outFrame.getHeight(),

            left, top);

    return outFrame;

}

/**

 * yuv数据的裁剪操作

 *

 * @param src        原始数据

 * @param width      原始的宽

 * @param height     原始的高

 * @param dst_width  输出的宽

 * @param dst_height 输出的高

 * @param left       裁剪的x的开始位置,必须为偶数,否则显示会有问题

 * @param top        裁剪的y的开始位置,必须为偶数,否则显示会有问题

 **/

public static native void crop(byte[] src, ByteBuffer yOut,

                               ByteBuffer uOut,

                               ByteBuffer vOut,

                               int yOutStride,

                               int uOutStride,

                               int vOutStride,

                               int width,

                               int height, int dst_width, int dst_height, int left, int top);

上面的裁剪需要传入一个原始数据的数组,得到原始数据的代码如下:

/**

     * q: 为什么要转换成NV21

     * a: 因为NV21是android系统的默认格式,而且NV21是YUV420SP格式,这种格式的特点是占用空间小,传输和存储都比较方便,适合移动设备

     * <p>

     * q: 为什么要转换成YUV420SP

     * a: 因为YUV420SP是NV21的一种变换格式,YUV420SP的特点是可以直接用于MediaCodec编码,而NV21不行

     * <p>

     * q: 为什么要转换成YUV420P

     * a: 因为YUV420P是YUV420SP的一种变换格式,YUV420P的特点是可以直接用于FFmpeg编码,而YUV420SP不行

     *

     * @param image

     * @return

     */

    public static byte[] getNV21FromImage(Image image) {

        long time1 = System.currentTimeMillis();

        int w = image.getWidth(), h = image.getHeight();

        int i420Size = w * h * 3 2;

        int picel1 = ImageFormat.getBitsPerPixel(ImageFormat.NV21);

        int picel2 = ImageFormat.getBitsPerPixel(ImageFormat.YUV_420_888);

        Image.Plane[] planes = image.getPlanes();

        //remaining0 = rowStride*(h-1)+w => 27632= 192*143+176

        int remaining0 = planes[0].getBuffer().remaining();

        int remaining1 = planes[1].getBuffer().remaining();

        //remaining2 = rowStride*(h/2-1)+w-1 =>  13807=  192*71+176-1

        int remaining2 = planes[2].getBuffer().remaining();

        //获取pixelStride,可能跟width相等,可能不相等

        int pixelStride = planes[2].getPixelStride();

        int rowOffest = planes[2].getRowStride();

        byte[] nv21 = new byte[i420Size];

        byte[] yRawSrcBytes = new byte[remaining0];

        byte[] uRawSrcBytes = new byte[remaining1];

        byte[] vRawSrcBytes = new byte[remaining2];

        planes[0].getBuffer().get(yRawSrcBytes);

        planes[1].getBuffer().get(uRawSrcBytes);

        planes[2].getBuffer().get(vRawSrcBytes);

        if (pixelStride == w) {

            //两者相等,说明每个YUV块紧密相连,可以直接拷贝

            System.arraycopy(yRawSrcBytes, 0, nv21, 0, rowOffest * h);

            System.arraycopy(vRawSrcBytes, 0, nv21, rowOffest * h, rowOffest * h / 2 1);

        else {

            byte[] ySrcBytes = new byte[w * h];

            byte[] uSrcBytes = new byte[w * h / 2 1];

            byte[] vSrcBytes = new byte[w * h / 2 1];

            for (int row = 0; row < h; row++) {

                //源数组每隔 rowOffest 个bytes 拷贝 w 个bytes到目标数组

                System.arraycopy(yRawSrcBytes, rowOffest * row, ySrcBytes, w * row, w);

                //y执行两次,uv执行一次

                if (row % 2 == 0) {

                    //最后一行需要减一

                    if (row == h - 2) {

                        System.arraycopy(vRawSrcBytes, rowOffest * row / 2, vSrcBytes, w * row / 2, w - 1);

                    else {

                        System.arraycopy(vRawSrcBytes, rowOffest * row / 2, vSrcBytes, w * row / 2, w);

                    }

                }

            }

            System.arraycopy(ySrcBytes, 0, nv21, 0, w * h);

            System.arraycopy(vSrcBytes, 0, nv21, w * h, w * h / 2 1);

        }

        return nv21;

    }

如上就是使用libyuv的旋转、翻转、缩放、裁剪的核心操作,如果需要将image转换成YuvFrame,可以如下操作,代码:

extern "C"

JNIEXPORT void JNICALL

Java_com_example_liveassistant_utils_YuvNativeUtil_convertToI420(JNIEnv *env, jclass thiz,

                                                                 jobject y, jobject u,

                                                                 jobject v, jint yStride,

                                                                 jint uStride, jint vStride,

                                                                 jint srcPixelStrideUv,

                                                                 jobject yOut, jobject uOut,

                                                                 jobject vOut,

                                                                 jint yOutStride, jint uOutStride,

                                                                 jint vOutStride,

                                                                 jint width, jint height) {

    uint8_t *yNative = (uint8_t *) env->GetDirectBufferAddress(y);

    uint8_t *uNative = (uint8_t *) env->GetDirectBufferAddress(u);

    uint8_t *vNative = (uint8_t *) env->GetDirectBufferAddress(v);

    uint8_t *yOutNative = (uint8_t *) env->GetDirectBufferAddress(yOut);

    uint8_t *uOutNative = (uint8_t *) env->GetDirectBufferAddress(uOut);

    uint8_t *vOutNative = (uint8_t *) env->GetDirectBufferAddress(vOut);

    libyuv::Android420ToI420(yNative, yStride,

                             uNative, uStride,

                             vNative, vStride,

                             srcPixelStrideUv,

                             yOutNative, yOutStride,

                             uOutNative, uOutStride,

                             vOutNative, vOutStride,

                             width, height);

}

public static YuvFrame convertToI420(Image image) {

    YuvFrame outFrame = FramesFactory.INSTANCE.instanceYuv(image.getWidth(), image.getHeight());

    convertToI420(image.getPlanes()[0].getBuffer(),

            image.getPlanes()[1].getBuffer(),

            image.getPlanes()[2].getBuffer(),

            image.getPlanes()[0].getRowStride(),

            image.getPlanes()[1].getRowStride(),

            image.getPlanes()[2].getRowStride(),

            image.getPlanes()[2].getPixelStride(),

            outFrame.getY(),

            outFrame.getU(),

            outFrame.getV(),

            outFrame.getYStride(),

            outFrame.getUStride(),

            outFrame.getVStride(),

            image.getWidth(),

            image.getHeight());

    return outFrame;

}

private static native void convertToI420(ByteBuffer y,

                                         ByteBuffer u,

                                         ByteBuffer v,

                                         int yStride,

                                         int uStride,

                                         int vStride,

                                         int srcPixelStrideUv,

                                         ByteBuffer yOut,

                                         ByteBuffer uOut,

                                         ByteBuffer vOut,

                                         int yOutStride,

                                         int uOutStride,

                                         int vOutStride,

                                         int width,

                                         int height);

在android项目上集成libyuv库以及使用libyuv库完成camera的缩放,旋转,翻转,裁剪操作相关推荐

  1. 在Android项目上集成Google语音(不使用手机自带引擎)

    需求: 最近需要在项目中需要集成各家的语音识别功能.包括讯飞,Alexa以及google的语音.前面两家的都有对应的api,集成到对应的项目中比较简单,这里只介绍如果集成Google的语音在项目上,像 ...

  2. Android平台上集成海康SDK(二)

    Android平台上集成海康SDK 以上是我之前写的一篇Android平台上集成海康SDK的文章,其中对于Android平台上集成海康SDK.基于海康SDK进行二次开发基本上进行了详细地介绍. 这篇文 ...

  3. Android项目上传到GItHub

    Android项目上传到GitHub管理_Mac 步骤 1.创建新的Anroid项目 2.GitHub创建新的代码仓库 3.GitHub远程版本库克隆到本地 3.1.进入项目文件夹 3.2把远程版本库 ...

  4. Android平台上集成大华SDK(二)

    Android平台上集成大华SDK 以上是我之前写的一篇Android平台上集成大华SDK的文章,其中对于Android平台上集成大华SDK.基于大华SDK进行二次开发基本上进行了详细地介绍. 这篇文 ...

  5. Android项目如何集成ZXing二维码扫描功能

    最近的项目有二维码扫描跳转网页的需求,就是利用手机摄像头,扫描并解析二维码内容,内容由生成二维码的时候定义,我项目现在的需求就是一个包含了网址的二维码,网上有生成二维码的工具,也可以自己开发一个. 搜 ...

  6. takephoto 框架_GitHub - Smecking/TakePhoto: 一款用于在Android设备上获取照片(拍照或从相册、文件中选择)、裁剪图片、压缩图片的开源工具库...

    TakePhoto是一款用于在Android设备上获取照片(拍照或从相册.文件中选择).裁剪图片.压缩图片的开源工具库,目前最新版本4.0.2. 3.0以下版本及API说明,详见TakePhoto2. ...

  7. Android平台上集成萤石SDK

    这篇文章,就Android平台上如何集成萤石SDK进行讲解. 前言: 萤石是海康威视集团旗下的一家做视频云的公司.我们接入萤石设备,实现实时预览.远程回放.抓图.切换画质等功能. 关于具体如何接入,包 ...

  8. Android项目中集成华为账号登录、支付

    最近项目中集成了华为账号登录与支付的功能,把踩过的坑和过程记录下来. 先看下支付效果图: 支付价格0.01请忽略,因为这是为了测试用的. 刚开始接到这个项目的时候我很奇怪,为什么要集成华为支付呢,原有 ...

  9. Android项目持续集成之Jenkins的使用

    原址 Jenkins拥有的特性包括:  1. 易于安装-只要把jenkins.war部署到servlet容器,不需要数据库支持.  2. 易于配置-所有配置都是通过其提供的web界面实现.  3. 集 ...

最新文章

  1. Java项目:宠物商城系统(java+Springboot+Maven+mybatis+Vue+mysql)
  2. WCFAppFabric :异常消息: 内存入口检查失败
  3. java springcloud版b2b2c社交电商spring cloud分布式微服务 (四) 断路器(Hystrix)
  4. Linux C: IO库函数,文件流缓冲,变参函数
  5. boost的chrono模块运行时解析的测试程序
  6. 域控下发脚本_域环境下做到单用户登陆控制脚本
  7. 高质量的设计灵感社区网站
  8. python爬虫知识点总结(七)PyQuery详解
  9. 电脑显示未安装任何音频输出设备_音频频谱分析仪插件Voxengo SPAN Plus介绍及安装教程...
  10. LintCode Copy Books
  11. 纯css 箭头,纯CSS实现小箭头的案例
  12. 小瘦牛虚拟无线路由器官方版
  13. HDU 1224(动态规划)
  14. 低功耗蓝牙开发权威指南--第三部分 主机 (第9-12章)
  15. 喷淋系统在安装算量软件中如何计算工程量?
  16. python简易电话簿系统_Python实现电话簿工具(代码分享)
  17. 如何搭建一个爬虫代理服务?
  18. linux 下strip工具,linux下使用strip如何对库和可执行文件进行裁减
  19. Virtex—5 GTP和Virtex—6 GTX间匹配通信研究及应用
  20. 计算机的it入门知识点,基础乐理知识点电脑基础知识IT计算机专业资料-基础乐理知识点(5页)-原创力文档...

热门文章

  1. 服务器如何解决被流量攻击
  2. Csharp日常笔记
  3. 微信jssdk已无力吐槽
  4. 安卓学习日志 Day01 — 界面布局
  5. strstr函数.c
  6. .Net 中使用Farpoint Web Spread 自定义CellType
  7. 如何使用 开源硬件Banana PI BPI-R2‘s GPIO-s
  8. 用遗传算法求解TSP问题
  9. react+antd的后台管理项目模板
  10. System.arraycopy()详解