我编写了一个使用Camera2
并且基本上使用两个输出的库项目:使用SurfaceTexture
的预览和使用YUV_420_888 ImageReader的处理输出。
通过将CaptureRequest.SCALER_CROP_REGION
设置为匹配所选的输出大小,可以避免对处理图像进行任何放大/缩小操作。
此输出组合当前适用于所有硬件级别,因为我当前使用4倍数码变焦。
我希望能够设置不同的缩放级别(可能是1倍,起初未知),并尽可能保留当前的性能。
为了支持硬件级别低于FULL
的设备,我唯一的选择似乎是使用一个输出目标(传感器大小的ImageReader YUV_420_888,保证为LEGACY级别),并以某种方式手动填充预览。
目标尺寸已为MAXIMUM
,因为我不希望进行任何放大/缩小操作,并且一开始不会知道缩放,因此会 ==> 实际的用户感知缩放必须是提供给预览的裁剪。
现在只有一个输出,我必须找到一种有效的方式:
最初,我想使用RenderScript,但由于它在库项目中不起作用,因此不得不放弃它。然后我尝试使用NDK,但这涉及处理YUV到RGB的转换(比Java快,但对于大图像仍然很慢)。
所以我现在正在考虑MediaCodec / EGL方法。但是,我没有太多经验,所以我有点迷路。我已经阅读了很多有关MediaCodec
的信息,据推测它可以使您skip the format conversion,但是我在解决这些CTS示例和理解如何链接ImageReader
表面时遇到了问题和预览表面(由SurfaceTexture
制成)。 This example被认为是相关的,但是我不知道如何交互。
大概我应该从YUV曲面创建一个InputSurface
,然后创建一个编码器,然后从预览曲面创建一个OutputSurface
,并分配一个进行裁剪的着色器,并为其配置解码器。
这是正确的方法吗?是否需要像here中那样管理所有缓冲区?我可以真正跳过转换吗?
会使用eglCreateWindowSurface
,as mentioned by Eddy Talvala be better吗?有人有很好的榜样吗?
在发现无法使用我想要的尺寸(UHD being the max, when available...)之前,我曾尝试(失败)以下列方式使用MediaCodec
(以减轻颜色格式转换的负担):
Surface
至Surface
==>将ImageReader
表面设置为input surface,将SurfaceTexture制成的表面设置为输出。
第一个限制是编解码器选择。编解码器似乎不支持大输入格式。使用MediaFormat.KEY_MAX_INPUT_SIZE
,MediaFormat.KEY_MAX_WIDTH
和MediaFormat.KEY_MAX_HEIGHT
也不起作用,did setting the input sizes to multiples of 16。
设置受编解码器支持的输入大小时,它仍然不起作用,大概是因为a Surface
can have only one producer and one consumer(不确定确切原因,也可能只是我)
Buffer
至Surface
==>将Camera2 Images
馈送到解码器。
getInputImage
(onInputBufferAvailable)返回非空图像Image
转换为连续的YUV I420字节缓冲区并将其馈送到解码器需要花费时间(本机代码),与直接使用本机方法相比,我不确定这是一个大胜利。