时间:2019-01-07 08:39:56

标签: java android bytebuffer

我需要从 IFrameCallback 获取位图,该位图用于处理 UVCCamera 预览中的 frame 。 ,但有一个例外:

  

java.lang.UnsupportedOperationException,位于   java.nio.ByteBuffer.arrayOffset

private final IFrameCallback callback = new IFrameCallback() {
    @override
    public void onFrame(final ByteBuffer frame) {
        new Thread(new Runnable() {
            byte[] bytes = new byte[frame.remaining()];
            frame.get(bytes);

            if(bytes.length > 0) {
                int offset = frame.arrayOffset();
                Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, offset, bytes.length - offset);
                ......
            }
        }).start();
    }
}

或者如果我使用 createBitmap 而不是 decodeByteArray ,则会出现此异常:

  

java.lang.RuntimeException:缓冲区不足以容纳像素   android.graphics.Bitmap.copyPixelsFromBuffer

private final IFrameCallback callback = new IFrameCallback() {
    @override
    public void onFrame(final ByteBuffer frame) {
        new Thread(new Runnable() {
            Bitmap bitmap = Bitmap.createBitmap(UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, Bitmap.Config.ARGB_8888);
            bitmap.copyPixelsFromBuffer(frame);
            ......
        }).start();
    }
}

因为预览大小为 1280 x 720 ,所以可以忽略 RuntimeException 问题。

关于从 ByteBuffer 获得 arrayOffset 的第一个异常是否有任何想法?

PS:我知道

  

UnsupportedOperationException-如果此缓冲区没有由   可访问数组

我的意思是:是否还有其他方法可以获取 arrayOffset ,或者是否不能这样做以及如何解决RuntimeException?

1 个答案:

答案 0 :(得分:0)

好吧,由于没有一个好的解决方案,我改变了从 IFrameCallback 获取位图的方法。

因为我已将 UVCCamera.PIXEL_FORMAT_NV21 格式应用于 UVCCamera

  

uvcCamera.setFrameCallback(frameCallback,   UVCCamera.PIXEL_FORMAT_NV21);

因此,我可以获取位图,只需转换 YuvImage

private ChannelBufferOutputStream stream = new ChannelBufferOutputStream(MessageBuffers.dynamicBuffer());
......
private final IFrameCallback callback = new IFrameCallback() {
    @override
    public void onFrame(final ByteBuffer frame) {
        new Thread(new Runnable() {
            @override
            public void run() {
                byte[] bytes = new byte[frame.remaining()];
                frame.get(bytes);

                if(bytes.length > 0) {
                    YuvImage yuvImage = new YuvImage(bytes, ImageFormat.NV21, UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, null);
                    bytes = null;

                    if(yuvImage.getYuvData().length > 0) {
                        yuvImage.compressToJpeg(new Rect(0, 0, yuvImage.getWidth(), yuvImage.getHeight()), 80, stream);
                        Bitmap bitmap = BitmapFactory.decodeByteArray(stream.buffer().array(), 0, stream.buffer().array().length);
                        ......
                    }
                }
            }
        }).start();
    }
}