如何在 MediaCodec 编码器和 CameraX 之间共享 Surface

2024-01-01

我想从以下位置获取图像CameraX(预览用例)并将它们编码为 h.264 视频MediaCodec。我怎样才能做到这一点? 我正在尝试的是,使用Surface从返回MediaCodec.createInputSurface() in Preview.Builder()通过使用Preview.setSurfaceProvider()。我继承了一个类Preview.SurfaceProvider然后在该设置中配置我的编码器并覆盖onSurfaceRequested()回来Surface from createInputSurface()。这预计会起作用吗?我真的可以共享这样的 Surface 并期望 CameraX 写入此 Surface 并填充我的编码器的输入吗?

是否有更有效的方法来对实时 CameraX 源进行编码?

注意:我使用的是 KOTLIN


我终于解决了这个问题OpenGL渲染器 https://android.googlesource.com/platform/frameworks/support/+/de44ffe38b6d7d2e78db7191dd679eb64b15b962/camera/integration-tests/coretestapp/src/main/java/androidx/camera/integration/core/OpenGLRenderer.java来自 CameraX OpenGL 测试。这是针对 CameraX beta 7 版本的。

像往常一样设置camerax,但使用2个预览:

val preview: Preview = Preview.Builder().apply {
    setTargetResolution(targetSize)
    setTargetRotation(rotation)
}.build()

val encoderPreview: Preview = Preview.Builder().apply {
    setTargetResolution(targetSize)
    setTargetRotation(rotation)
}.build()

cameraProvider.unbindAll()

camera = cameraProvider.bindToLifecycle(
        lifecycleOwner,
        cameraSelector,
        preview,
        encoderPreview
)

preview.setSurfaceProvider(viewFinder.createSurfaceProvider())

然后初始化编码器:

val format = MediaFormat.createVideoFormat(
        "video/avc", resolution.width, resolution.height
)

format.setInteger(
        MediaFormat.KEY_COLOR_FORMAT,
        MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface
)

format.setInteger(MediaFormat.KEY_BIT_RATE, 500 * 1024)
format.setInteger(MediaFormat.KEY_FRAME_RATE, 25)
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 3)

encoder = MediaCodec.createEncoderByType("video/avc")

encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)

并连接两者:

private val glRenderer = OpenGLRenderer()

surface = encoder.createInputSurface()

glRenderer.attachInputPreview(encoderPreview)

glRenderer.setFrameUpdateListener(executor, Consumer<Long> {
    // when frame is written to output surface
    publishFrame()
})

encoder.start()

glRenderer.attachOutputSurface(surface, resolution, 0)

发布框架功能:

private fun publishFrame() {
    val index: Int = try {
        encoder.dequeueOutputBuffer(info, 10 * 1000)
    } catch (e: Exception) {
        -1
    }

    if (!isRunning.get()) {
        return
    }

    if (index >= 0) {
        val outputBuffer = encoder.getOutputBuffer(index)
        if (outputBuffer == null) {
            return
        }

        if (info.size > 0) {
            outputBuffer.position(info.offset)
            outputBuffer.limit(info.offset + info.size)
            info.presentationTimeUs = System.nanoTime() / 1000

            // do something with frame
        }

        encoder.releaseOutputBuffer(index, false)

        if (info.flags.hasFlag(MediaCodec.BUFFER_FLAG_END_OF_STREAM)) {
            return
        }
    }
}

注意FRAME_RATE编码器中的参数不受尊重,您将根据发布到输出表面的帧数(调用了多少次)来获得帧速率publishFrame)。控制帧速率变化private void renderLatest()函数于OpenGLRenderer(丢帧,不调用renderTexture).

编辑:较新的解决方案作为camerax谷歌组对话的一部分出现可以在这里找到 https://groups.google.com/a/android.com/g/camerax-developers/c/pxUHvlDta54

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 MediaCodec 编码器和 CameraX 之间共享 Surface 的相关文章

  • 如何在构建 Android 应用程序的发布版本之前删除所有调试日志记录调用?

    根据谷歌的说法 我必须 停用源代码中对 Log 方法的任何调用 在将我的 Android 应用程序发布到 Google Play 之前 摘自第 3 节出版清单 https developer android com studio publi
  • Android ListView数组索引过滤后越界

    我认为这是专家的问题 我接到电话getView with positon 出界来自ListView数据列表 当我使用适配器过滤器时会发生这种情况 过滤器publishResults 方法使用小于原始列表的过滤列表填充数据 当新的过滤列表时似
  • 如果我使用单例,在哪里关闭 SQLiteOpenHelper

    我有以下课程允许用户获得SQLiteOpenHelper object import android content Context public class DBUtils private DBUtils private static D
  • ViewPager 开关 FragmentPagerAdapter

    我有一个ViewPager这是由一个FragmentPagerAdapter 我想将第一个适配器更换为另外两个 问题是之前加载的所有页面 同时具有第一个适配器 仍然是旧的页面 我查看了源代码FragmentPagerAdapter并猜测问题
  • 我应该保留远程数据库的本地副本吗?

    我正在开发一个应用程序 基本上允许人们创建 加入和管理其他人的群组 群组内的人也可以互相发送消息 我一直在想哪条路会更好 保留包含所有信息的远程数据库 包括发送给用户和从用户发送的消息 并让应用程序在每次需要信息时查询服务器 甚至是它以前见
  • 安装 OpenGL ES 并编译 Android 代码

    我刚刚开始在 android 上学习 OpenGL ES 使用这本书 https rads stackoverflow com amzn click com 1430226471 并遇到了采用的问题source http apress co
  • 我应该将 onClickListener 放在自定义 ListView 的哪里?

    我正在定制ListView包含 a 的行数CheckBox and a TextView 在我使用自定义之前ListViews使用 SimpleCursorAdapter 我的onListItemClick 工作得很好 我读过我必须添加一个
  • FFmpeg 不适用于 android 10,直接进入 onFailure(String message) 并显示空消息

    我在我的一个项目中使用 FFmpeg 进行视频压缩 在 Android 10 Google Pixel 3a 上 对于发送执行的任何命令 它会直接进入 onFailure String message 并显示空消息 所以我在我的应用程序 g
  • 此版本不符合 Google Play 64 位要求,添加库后仍然出现错误

    我正在 Play 商店上传一个视频编辑器应用程序 其中包含带有一些本机代码的库 所以我通过将其添加到 gradle 来使其兼容 64 位 ndk abiFilters armeabi v7a arm64 v8a x86 x86 64 添加了
  • 将原生 Twilio Android SDK 与 Flutter 集成

    我正在尝试使用 flutter 创建 IP 语音 VOIP 移动应用程序 我还没有看到 twilio 语音 api 的 flutter 插件的实现 所以我使用 MethodChannel 将我的应用程序与本机 android 语音 api
  • NativeScript 错误。在列表模板中找到多个视图

    我有这样的ListView
  • 使用 firebase 按最新消息对聊天列表进行排序

    我不知道为什么我陷入了一个问题chatList不按最后一条消息时间或最新消息排序 我尝试过存储timestamp在数据库中和订单子依据时间戳 但它仍然不起作用 不起作用意味着列表不会在每条消息后排序 并继续将列表显示为在第一条消息后排序 看
  • 如何获取 Android 中临时文件的文件大小?

    如果我使用 openFileOutput 创建并写入临时文件 写入完成后如何获取文件大小 我希望这可以帮助你 File file new File selectedPath int file size Integer parseInt St
  • 使用MockWebServer暂停功能测试

    我正在测试使用 MockWebServer 的挂起函数返回结果的 api 但它不适用于 runBlockingTest testCoroutineDispatcher testCorounieScope 除非launch使用builder
  • Listview里面只有一个Element

    您好 我正在尝试将列表视图放入列表视图中的列表视图中 唯一的问题是只有第一个列表视图正确显示所有元素 此后的每个列表视图仅包含一个元素 UPDATE 创建我自己的不可滚动列表视图解决了这个问题 https stackoverflow com
  • 无法在 BlackBerry Playbook 上设置音量

    我在更改黑莓游戏书的音量时遇到问题 首先 我将 Android 应用程序重新打包到 Palybook 应用程序 我需要使用搜索栏更改黑莓剧本的音量 并在搜索监听器中设置音频管理器音量 这是代码 audioManager AudioManag
  • Android:毫米或英寸尺寸的视图尺寸不正确

    我有一个布局高度为 10mm 的按钮 在大多数设备上看起来都是正确的 但在 Lg Optimus 2X 和 Motorola Defy 上 按钮的尺寸大约只有一半 我检索了这些设备上的 DisplayMetrics 信息 这是一个简短的概述
  • 如何从耳机插孔获取电力?

    我的问题是是否有人知道如何创建一个可以通过设备的耳机插孔发送电荷的 Android 应用程序 就像这个视频中那样 该视频展示了一款 iPhone 应用程序 可控制插入耳机插孔的 LED 我想知道如何访问该设备来发送电信号 抱歉我的英语不是我
  • Eclipse:缺少 Java 构建路径

    我正在尝试使用 Eclipse 来使用适用于 Android 的 Google SDK 教程 我能够让前两个项目正常工作 但是当运行第三个 R java 时消失了 所以我放弃了 我根据练习 3 的解决方案集制作了一个全新的包 它充满了错误
  • 我可以在 Android Market 上出售我的 SL4A 应用程序吗?

    Closed 这个问题是无关 help closed questions 目前不接受答案 我想使用 SL4A 在 Android 上使用 Python 开发一个应用程序 并且我想知道是否可以将其作为应用程序在 Android Market

随机推荐