我正在try 创建一款能够支持四个输出的Camera2 CameraCaptureSession:

  1. 屏幕预览(SurfaceView,高达1080p)
  2. 照片截图(ImageReader张,最多8k张照片)
  3. 视频采集(MediaRecorder/MediaCodec,高达4k视频)
  4. 帧处理(ImageReader帧,最高4K视频帧)

不幸的是,Camera2不支持同时附加所有这四个输出(表面),所以我将不得不做出妥协.

对我来说,最合乎逻辑的折衷方案是将两个视频捕获管道合并为一个,以便帧处理输出(#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)

..从MediaRecorderSurface

val surface = MediaCodec.createPersistentInputSurface()
val recorder = MediaRecorder(context)
..
recorder.setInputSurface(surface)

我在想,我可能需要一个带有直通着色器的OpenGL管线--但我不知道如何从ImageReader‘S Image到OpenGL纹理,所以这里的任何帮助都将不胜感激.


我try 了什么:我研究了Hardware Buffer 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级别28.因此,我仍然需要一个适用于API级别23及以上的解决方案.image.getPlanes()函数为YUV数据返回三个ByteBuffer,但不确定如何从那里创建OpenGL纹理.

推荐答案

我(差不多)想明白了!我找到了ImageWriter API,这正是我要从头开始重建的东西--一条从图像到曲面的直通管道.

因此,现在我将摄像机帧传输到ImageReader,调用具有Image的帧处理器,然后使用ImageWriter作为中间人将Image传递到MediaRecorder:)

val size = config.getOutputSizes(ImageFormat.PRIVATE).max()

// Video Recorder Surface. We need to stream Frames here if we are recording.
val surface = recordingSession.surface
val imageWriter = ImageWriter.newInstance(surface,
                                          VIDEO_OUTPUT_BUFFER_SIZE)

// Image Reader Surface. We stream Frames here for Frame Processor or Recording.
val flags = HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE or HardwareBuffer.USAGE_VIDEO_ENCODE
val imageReader = ImageReader.newInstance(size.width,
                                          size.height,
                                          ImageFormat.PRIVATE,
                                          VIDEO_OUTPUT_BUFFER_SIZE,
                                          flags)

imageReader.setOnImageAvailableListener({ reader ->
  val image = reader.acquireNextImage() ?: return
  image.timestamp = System.nanoTime()

  // Call JS Frame Processor
  frameProcessor?.call(image)
                                         
  // If recording, write to Video File             
  if (isRecording) {
    imageWriter.queueInputImage(image)
  }

  image.close()
}, CameraQueues.videoQueue)

// Camera only streams frames into one single Surface
cameraSession.configure(.., imageReader.surface)

我现在唯一的问题是,所产生的视频记录有时会在大约3秒的记录后出现~1秒的长仰卧起坐,我不知道为什么.也许我应该用MediaCodec而不是MediaRecorder.也许我应该用一辆不同的ImageFormat.也许我应该调查一下生成的.mp4文件,看看出了什么问题.也许我应该修复图像时间戳.我不知道.

此外,Logcat还会收到以下垃圾邮件:

2023-08-17 11:38:17.977  3780-3899  GraphicBufferSource     com.mrousavy.camera.example          W  released unpopulated slots: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]
2023-08-17 11:38:18.021  3780-3899  GraphicBufferSource     com.mrousavy.camera.example          W  released unpopulated slots: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]
2023-08-17 11:38:18.050  3780-3899  GraphicBufferSource     com.mrousavy.camera.example          W  released unpopulated slots: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]
2023-08-17 11:38:18.082  3780-3899  GraphicBufferSource     com.mrousavy.camera.example          W  released unpopulated slots: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]
2023-08-17 11:38:18.113  3780-3899  GraphicBufferSource     com.mrousavy.camera.example          W  released unpopulated slots: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]
2023-08-17 11:38:18.146  3780-3899  GraphicBufferSource     com.mrousavy.camera.example          W  released unpopulated slots: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]
2023-08-17 11:38:18.179  3780-3899  GraphicBufferSource     com.mrousavy.camera.example          W  released unpopulated slots: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]

但是,嘿--它会录下一段视频.这是一个良好的开端.

Android相关问答推荐

如何使用喷气背包压缩让Animated Image Vector每次动画化一条路径?

Android Jetpack Compose Material3主题配色方案

安卓Gradle看不到dagger 柄

Android和Rust,OpenSSL交叉编译在ARM V7上链接失败

每次重启Android时预填入Room数据库

从安卓S原生库的资源中读取json文件

在androidStudio中,如何使用带有ResolutionStrategy的ResolutionSelector而不是setTargetResolve()?

(已解决)从最近的应用程序打开应用程序时出错

以下代码如何在 Android 上运行

如何在 Jetpack Compose 中的特定位置绘制图像

Android 设备断开连接后发送的 BLE 蓝牙数据

每次在 Jetpack Compose 中调用导航

PullRefreshIndicator 与 ScrollableTabRow 重叠

Unity:Android 上随机接近零的 FPS 下降(提供了很多线索)

Android Studio Emulator Internet 连接问题仅是第一次

如何在 TextInputEdit 中调整可绘制对象的大小

在 Jetpack Compose 中 Select 要省略的文本

Jetpack Compose 中的按钮上的文本未更新

为什么我不能在屏幕外拿任何物体

AndroidX Room 生成类错误:类是公共的,应在名为 class.java 的文件中声明