android 硬编码保存mp4

目录

java imagereader编码保存

java NV21toYUV420SemiPlanar 编码保存视频用:

imageReader获取nv21

jni NV12toYUV420SemiPlanar函数:


代码来自博客:

【Android Camera2】彻底弄清图像数据YUV420_888转NV21问题/良心教学/避坑必读!_yuv420888转nv21_奔跑的鲁班七号的博客-CSDN博客

java imagereader编码保存

//Planar格式(P)的处理
  private static ByteBuffer getuvBufferWithoutPaddingP(ByteBuffer uBuffer,ByteBuffer vBuffer, int width, int height, int rowStride, int pixelStride){
        int pos = 0;
        byte []byteArray = new byte[height*width/2];
        for (int row=0; row

java NV21toYUV420SemiPlanar 编码保存视频用:

        public byte[] NV21toYUV420SemiPlanar(byte[] nv21, int width, int height) {
            byte[] yuv420sp = new byte[width * height * 3 / 2];
            int frameSize = width * height;
            int i, j;

            System.arraycopy(nv21, 0, yuv420sp, 0, frameSize); // Y分量直接复制

            for (i = 0; i < frameSize / 4; i++) {
                j = i * 2;
                // NV21的UV分量交替排列,转为NV12需要调换U和V的位置
                yuv420sp[frameSize + j] = nv21[frameSize + j + 1]; // U分量
                yuv420sp[frameSize + j + 1] = nv21[frameSize + j]; // V分量
            }
            return yuv420sp;
        }

imageReader获取nv21

plane[0] + plane[2] =NV21;; plane[0] + plane[1] =NV12

Image image = reader.acquireLatestImage();
if (image == null) {
    return;
}

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

ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
int ySize = yBuffer.remaining();

ByteBuffer vBuffer = image.getPlanes()[2].getBuffer();
int vSize = vBuffer.remaining();

byte[] nv21_s = new byte[WIDTH*HEIGHT * 3 / 2];

try {
    yBuffer.get(nv21_s, 0, yBuffer.remaining());
    vBuffer.get(nv21_s, ySize, vBuffer.remaining());
    imageQueue.put(nv21_s);
} catch (Exception e) {
    throw new RuntimeException(e);
}


image.close();

注:

1.这种方式会缺最后一个像素的U分量或V分量,如果追求完美,对NV21,可以从plane[1]中取出最后的值追加到末尾;对NV12则是在plane[2]中取出最后的值追加到末尾;

2.只适用于图像宽度为8的整数倍的情况,否则因为需要做内存对齐,后面会补0,,导致image.getWidth()< plane.getRowStride(),这就需要对每一行舍去后面多余的0,然后再拼接,效率会低很多。

jni NV12toYUV420SemiPlanar函数:

    public  native byte[] NV12toYUV420SemiPlanar(byte[] data, int w, int h);
extern "C"

JNIEXPORT jbyteArray JNICALL Java_com_sandstar_ai_objectdetector_ObjectDetector_NV12toYUV420SemiPlanar
        (JNIEnv* env, jobject, jbyteArray nv12, jint width, jint height) {
    jbyte* nv12_bytes = env->GetByteArrayElements(nv12, NULL);
    jsize nv21_length = env->GetArrayLength(nv12);

    int frameSize = width * height;

    std::vector yuv420sp(nv21_length);

    std::memcpy(yuv420sp.data(), nv12_bytes, frameSize); // copy Y

    for (int i = 0; i < frameSize / 4; ++i) {
        int j = i * 2;
        yuv420sp[frameSize + j] = nv12_bytes[frameSize + j + 1]; // copy V
        yuv420sp[frameSize + j + 1] = nv12_bytes[frameSize + j]; // copy U
    }

    env->ReleaseByteArrayElements(nv12, nv12_bytes, 0);

    // Create a new byte array and put the data into it
    jbyteArray result = env->NewByteArray(nv21_length);
    env->SetByteArrayRegion(result, 0, nv21_length, reinterpret_cast(yuv420sp.data()));

    return result;
}

你可能感兴趣的:(android开发,java,开发语言)