¿Android convierte la imagen de ImageReader a la matriz de bytes YCbCr_420_SP (NV21) usando el script de renderizado?

Actualmente estoy trabajando conJavacv que hace uso depublic void onPreviewFrame(byte[] data, Camera camera) función de cámara

Como la cámara está en desuso, he estado investigandocamera2 yProyección de medios. Ambas bibliotecas hacen uso deClase ImageReader.

Actualmente ejemplifico talImageReader con el siguiente código:

ImageReader.newInstance(DISPLAY_WIDTH, DISPLAY_HEIGHT, PixelFormat.RGBA_8888, 2);

Y adjunte unOnImageAvailableListener Me gusta esto:

 private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
            = new ImageReader.OnImageAvailableListener() {

        @Override
        public void onImageAvailable(ImageReader reader) {

            mBackgroundHandler.post(new processImage(reader.acquireNextImage()));
        }

He intentado usar elRGBA_8888 formato con Javacv según este hilo:https://github.com/bytedeco/javacv/issues/298 Pero eso no funciona para mí.

En cambio, estaba pensando en usarRenderizar script para convertir estosImagens aNV,21(YUV_420_SP) formato (que es la salida predeterminada de la cámara en elonPreviewFrame función) ya que eso funcionó para mí con elcamera biblioteca.

También he leído publicaciones comoéste yeste sitio web para hacer la conversión, pero estos no funcionaron para mí y me temo que serán demasiado lentos. Además, mi conocimiento de C es muy limitado. Básicamente parece que quiero la operación inversa dehttps://developer.android.com/reference/android/renderscript/ScriptIntrinsicYuvToRGB.html

Entonces, ¿cómo puedes pasar de unImage a una matriz de bytes que coincidiría con la salida delonPreviewFrame función, es decirNV21(YUV_420_SP) ¿formato? Preferiblemente usando Renderscript ya que es más rápido.

Editar 1:

He intentado usarImageFormat.YUV_420_888 pero fue en vano. Seguí recibiendo errores comoThe producer output buffer format 0x1 doesn't match the ImageReader's configured buffer format. Volví aPixelFormat.RGBA_8888 y descubrí que solo hay un avión en elImageObject. El búfer de bytes de este plano es de tamaño ancho * alto * 4 (un byte para R, G, B, A, respectivamente). Así que intenté convertir esto aNV21 formato.

Modifiqué el código deesta respuesta para producir la siguiente función:

void RGBtoNV21(byte[] yuv420sp, byte[] argb, int width, int height) {
    final int frameSize = width * height;

    int yIndex = 0;
    int uvIndex = frameSize;

    int A, R, G, B, Y, U, V;
    int index = 0;
    int rgbIndex = 0;

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {

            R = argb[rgbIndex++];
            G = argb[rgbIndex++];
            B = argb[rgbIndex++];
            A = argb[rgbIndex++];

            // RGB to YUV conversion according to
            // https://en.wikipedia.org/wiki/YUV#Y.E2.80.B2UV444_to_RGB888_conversion
            Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
            U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
            V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;

            // NV21 has a plane of Y and interleaved planes of VU each sampled by a factor
            // of 2 meaning for every 4 Y pixels there are 1 V and 1 U.
            // Note the sampling is every other pixel AND every other scanline.
            yuv420sp[yIndex++] = (byte) ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
            if (i % 2 == 0 && index % 2 == 0) {
                yuv420sp[uvIndex++] = (byte) ((V < 0) ? 0 : ((V > 255) ? 255 : V));
                yuv420sp[uvIndex++] = (byte) ((U < 0) ? 0 : ((U > 255) ? 255 : U));
            }
            index++;
        }
    }
}

e invocarlo usando:

int mWidth = mImage.getWidth();
int mHeight = mImage.getHeight();

byte[] rgbaBytes = new byte[mWidth * mHeight * 4];
mImage.getPlanes()[0].getBuffer().get(rgbaBytes);
mImage.close();

byte[] yuv = new byte[mWidth * mHeight * 3 / 2];
RGBtoNV21(yuv, rgbaBytes, mWidth, mHeight);

aquímImage es unImage objeto producido por miImageReader.

Sin embargo, esto produce un resultado similar a esta imagen:

que está claramente malformado Parece que mi conversión está desactivada, pero no puedo entender qué exactamente.

Respuestas a la pregunta(1)

Su respuesta a la pregunta