我如何区分imageReader相机API 2中的NV21和YV12编码?

uel*_*rdi 6 android yuv android-camera2

我正在开发自定义相机API 2应用程序,我注意到当我使用ImageReader回调时,某些设备上的捕获格式转换是不同的.

例如在Nexus 4中工作不正常并且在Nexus5X中看起来没问题,这是输出.

在此输入图像描述

我以这种形式初始化ImageReader:

mImageReader = ImageReader.newInstance(320, 240, ImageFormat.YUV_420_888,2); 
Run Code Online (Sandbox Code Playgroud)

而我的回调是简单的回调ImageReader回调.

 mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {

    @Override
    public void onImageAvailable( ImageReader reader) {

       try {
             mBackgroundHandler.post(
                 new ImageController(reader.acquireNextImage())
             );
        }
        catch(Exception e)
        {
          //exception
        }
        }
Run Code Online (Sandbox Code Playgroud)

};

在Nexus 4的情况下:我有这个错误.

D/qdgralloc: gralloc_lock_ycbcr: Invalid format passed: 0x32315659
Run Code Online (Sandbox Code Playgroud)

当我尝试在两个设备中编写原始文件时,我有这些不同的图像.所以我知道Nexus 5X图像具有NV21编码,而Nexus 4具有YV12编码. 在此输入图像描述

我找到了图像格式的规范,我尝试在ImageReader中获取格式.有YV12和NV21选项,但显然,当我尝试获取格式时,我得到YUV_420_888格式.

 int test=mImageReader.getImageFormat();
Run Code Online (Sandbox Code Playgroud)

那么有没有办法让相机输入格式(NV21或YV12)区分相机类中的这种编码类型?CameraCharacteristics可能吗?

提前致谢.

垂发.PD:我使用OpenGL显示RGB图像,我使用Opencv进行转换为YUV_420_888.

Ale*_*ohn 3

YUV_420_888 是一个包装器,可以托管(除其他外)NV21 和 YV12 图像。您必须使用平面和步幅来访问各个颜色:

ByteBuffer Y = image.getPlanes()[0];
ByteBuffer U = image.getPlanes()[1];
ByteBuffer V = image.getPlanes()[2];
Run Code Online (Sandbox Code Playgroud)

如果底层像素采用 NV21 格式(如 Nexus 4),则 PixelStride 将为 2,并且

int getU(image, col, row) {
    return getPixel(image.getPlanes()[1], col/2, row/2);
}

int getPixel(plane, col, row) {
    return plane.getBuffer().get(col*plane.getPixelStride() + row*plane.getRowStride());
}
Run Code Online (Sandbox Code Playgroud)

我们采用半列和半行,因为这是 U 和 V(色度)平面在 420 图像中的存储方式。

此代码用于说明,效率非常低,您可能希望使用get(byte[], int, int)、 或通过片段着色器或通过本机代码中的 JNI 函数 GetDirectBufferAddress 批量访问像素。您不能使用 method plane.array(),因为平面保证是直接字节缓冲区。