我正在尝试创建一个能够具备四个输出功能的Camera2 CameraCaptureSession:
1. 屏幕预览 (SurfaceView, 最高1080p) 2. 拍照 (ImageReader, 最高8k分辨率) 3. 录制视频 (MediaRecorder/MediaCodec, 最高4k分辨率) 4. 帧处理 (ImageReader, 最高4k视频帧)
不幸的是,Camera2并不支持同时连接这四个输出(Surface),所以我必须做出妥协。
在我看来,最合理的妥协方案是将两个视频捕获管道合并为一个,这样帧处理输出(#4, ImageReader)就可以重定向到视频捕获输出 (#3, MediaRecorder)。
那么如何从ImageReader中写入图像呢?
从
我在考虑这里可能需要一个OpenGL管线,使用一个透传着色器 - 但是我不知道如何将
我尝试了一下:我研究了HardwareBuffer的API,具体来说。
我觉得这个可能行得通,但它需要API Level 28。所以我仍然需要一个适用于API Level 23及以上的解决方案。`image.getPlanes()`函数为我返回了三个`ByteBuffer`,其中包含YUV数据,但我不确定如何从中创建OpenGL纹理..
1. 屏幕预览 (SurfaceView, 最高1080p) 2. 拍照 (ImageReader, 最高8k分辨率) 3. 录制视频 (MediaRecorder/MediaCodec, 最高4k分辨率) 4. 帧处理 (ImageReader, 最高4k视频帧)
不幸的是,Camera2并不支持同时连接这四个输出(Surface),所以我必须做出妥协。
在我看来,最合理的妥协方案是将两个视频捕获管道合并为一个,这样帧处理输出(#4, ImageReader)就可以重定向到视频捕获输出 (#3, MediaRecorder)。
那么如何从ImageReader中写入图像呢?
val imageReader = ImageReader.newInstance(4000, 2256, ImageFormat.YUV_420_888, 3)
imageReader.setOnImageAvailableListener({ reader ->
val image = reader.acquireNextImage() ?: return@setOnImageAvailableListener
callback.onVideoFrameCaptured(image)
}, queue.handler)
val captureSession = device.createCaptureSession(.., imageReader.surface)
从
MediaRecorder
录制进入Surface
?val surface = MediaCodec.createPersistentInputSurface()
val recorder = MediaRecorder(context)
..
recorder.setInputSurface(surface)
我在考虑这里可能需要一个OpenGL管线,使用一个透传着色器 - 但是我不知道如何将
ImageReader
的Image
转换为OpenGL纹理,所以希望能得到帮助。
我尝试了一下:我研究了HardwareBuffer的API,具体来说。
auto clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
...
auto image = eglCreateImageKHR(display,
EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID,
clientBuffer,
attribs);
...
glEGLImageTargetTexture2DOES(GR_GL_TEXTURE_EXTERNAL, image);
我觉得这个可能行得通,但它需要API Level 28。所以我仍然需要一个适用于API Level 23及以上的解决方案。`image.getPlanes()`函数为我返回了三个`ByteBuffer`,其中包含YUV数据,但我不确定如何从中创建OpenGL纹理..
SurfaceTexture
创建的Surface
与CameraCaptureSession
吗?这样可以将视频帧作为OpenGL外部纹理可用。 - dev.bmaxImage
实例,因为我使用其他只接受Image
作为参数的机器学习API。 - mrousavyImageReader
,然后通过OpenGL管线来绘制到视频录制表面。 - mrousavy