- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我需要对实时摄像机数据(仅来自Y平面)进行CPU端只读处理,然后在GPU上进行渲染。在处理完成之前,不应该渲染帧(因此,我并不总是希望从摄像机渲染最新的帧,而只是想渲染CPU端已完成处理的最新帧)。渲染与摄影机处理是分离的,即使摄影机帧到达的速率低于该速率,目标还是要达到60 FPS。
在Lowest overhead camera to CPU to GPU approach on android上有一个相关但较高级的问题
为了更详细地描述当前设置:我们有一个用于相机数据的应用程序侧缓冲池,其中的缓冲区为“空闲”,“显示中”或“待显示”。当来自摄像机的新帧到达时,我们将获取一个可用缓冲区,将其存储在其中(如果实际数据位于某些系统提供的缓冲池中,则将其存储在其中),进行处理并将结果存储在缓冲区中,然后将缓冲区设置为“待显示”。在渲染器线程中,如果在渲染循环开始时有任何缓冲区“待显示”,我们将其锁存为一个“在显示中”,渲染照相机,并使用从该显示器计算出的已处理信息来渲染其他内容。相机镜框。
感谢@fadden对上面链接的问题的回答,我现在了解了android camera2 API的“并行输出”功能在各种输出队列之间共享缓冲区,因此,至少在现代android上,不应该涉及数据的任何拷贝。
在一条评论中,有人建议我可以同时锁住SurfaceTexture和ImageReader输出,并且只需“坐在缓冲区上”,直到处理完成即可。不幸的是,由于我们仍然希望以60 FPS的速度进行分离的渲染,因此我认为这不适用于我的情况,并且在处理新的帧以确保不会出现问题时,仍然需要访问上一帧不同步。
我想到的一种解决方案是拥有多个SurfaceTexture-在我们的每个应用程序端缓冲区中都有一个(我们目前使用3个)。通过这种方案,当我们获得一个新的相机框架时,我们将从应用程序端池中获得一个空闲缓冲区。然后,我们将在ImageReader上调用acquireLatestImage()
以获取要处理的数据,并在可用缓冲区的SurfaceTexture上调用updateTexImage()
。在渲染时,我们只需要确保“in display”缓冲区中的SufaceTexture是绑定(bind)到GL的SufaceTexture,并且大多数情况下所有内容都应该同步(因为@fadden评论说,调用updateTexImage()
和acquireLatestImage()
之间存在竞争但是该时间窗口应该足够小,以使其变得很少见,并且无论如何使用缓冲区中的时间戳可能是可分解且可修复的)。
我在文档中注意到,只有将SurfaceTexture绑定(bind)到GL上下文时才能调用updateTexImage()
,这表明我也需要在相机处理线程中使用GL上下文,以便相机线程可以在“免费”的SurfaceTexture上执行updateTexImage()
。缓冲区,而渲染线程仍能够从“显示中”缓冲区中的SurfaceTexture进行渲染。
因此,对于以下问题:
最佳答案
有趣的问题。
背景资料
具有多个具有独立上下文的线程非常常见。每个使用硬件加速的View渲染的应用程序在主线程上都有一个GLES上下文,因此任何使用GLSurfaceView(或使用SurfaceView或TextureView和一个独立的渲染线程滚动自己的EGL)的应用程序都在积极地使用多个上下文。
每个TextureView内部都有一个SurfaceTexture,因此任何使用多个TextureViews的应用程序都在单个线程上具有多个SurfaceTexture。 (该框架的实现中实际上是had a bug,它导致了多个TextureViews的问题,但这是一个高级问题,而不是驱动程序问题。)
SurfaceTexture是a/k/a GLConsumer,不会进行大量处理。当帧从源(在您的情况下为摄像机)到达时,它将使用一些EGL函数将缓冲区“包装”为“外部”纹理。您不能在没有EGL上下文的情况下进行这些EGL操作,这就是为什么SurfaceTexture必须附加到其中的原因,并且如果当前的上下文不正确,也无法将新框架放入纹理中。您可以从the implementation of updateTexImage()
中看到,它正在使用缓冲区队列,纹理和围墙来做很多不可思议的事情,但是它们都不要求复制像素数据。您真正占用的唯一系统资源是RAM,如果要捕获高分辨率图像,这并不是很重要的事情。
连接
EGL上下文可以在线程之间移动,但一次只能在一个线程上“当前”。来自多个线程的同时访问将需要大量不良同步。给定线程只有一个“当前”上下文。 OpenGL API已从具有全局状态的单线程演变为多线程,并且他们没有重写API,而是将状态推到了线程本地存储中,因此采用了“当前”的概念。
可以创建在它们之间共享某些东西(包括纹理)的EGL上下文,但是如果这些上下文在不同的线程上,则在更新纹理时必须非常小心。 Grafika提供了getting it wrong的一个很好的例子。
SurfaceTextures构建在具有生产者-消费者结构的BufferQueue之上。 SurfaceTextures的有趣之处在于它们同时包含了两面,因此您可以在一个过程中将数据提供到另一侧,而另一侧则可以拉出数据(例如,与SurfaceView不同,那里的使用者很远)。像所有Surface东西一样,它们是在Binder IPC之上构建的,因此您可以从一个线程提供Surface,并在另一个线程(或进程)中安全地updateTexImage()
。安排API,以便您在用户端(您的过程)创建SurfaceTexture,然后将引用传递给生产者(例如,主要在mediaserver
过程中运行的相机)。
实现
如果您经常连接和断开BufferQueue,则会导致大量开销。因此,如果要让三个SurfaceTextures接收缓冲区,则需要将所有三个连接到Camera2的输出,并让它们全部接收“广播的缓冲区”。然后,您将以循环方式updateTexImage()
。由于SurfaceTexture的BufferQueue在“异步”模式下运行,因此每次调用时都应始终获取最新的帧,而无需“耗尽”队列。
直到Lollipop时代的BufferQueue多输出更改和引入Camera2之前,这种安排才真正可行,所以我不知道是否有人尝试过这种方法。
所有SurfaceTextures都将附加到相同的EGL上下文,最好是在View UI线程之外的其他线程中,因此您不必为当前问题而战。如果要从另一个线程中的第二个上下文访问纹理,则需要使用SurfaceTexture attach/detach API调用,该调用明确支持此方法:
A new OpenGL ES texture object is created and populated with the SurfaceTexture image frame that was current at the time of the last call to detachFromGLContext().
updateTexImage()
-但是您需要采取通常的步骤来确保线程之间进行通信时的同步。
getTimestamp()
调用,因为这将大大简化从相机匹配缓冲区的过程。
关于android - Android上的零拷贝相机处理和渲染管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37592934/
有人能给我一些代码示例,了解如何从相机捕获“完整”图像,然后在“startActivityForResult”中将其转换为字节,以及显示在 imageView 中的位图。任何帮助将不胜感激。 山姆 最
我有一个带有两个圆的组,当我用平移过渡移动其中一个时,我应该看到静止的一个保持在中心(位于场景图的中间),而另一个移动。取而代之的是,“摄像机”跟随移动的圆圈,使其看起来好像都在分开。 有没有一种方法
我希望停止 Phonegap 将图片保存到 iOS 上的相机胶卷。 我发现了一种可能的解决方案,但我不太喜欢它。该解决方案需要通过删除这行代码来 fork phonegap API。 UIImageW
我最近开始使用 JOGL,我知道如何在 Canvas 上创建和绘制对象,但我找不到有关如何设置和旋转相机的教程或说明。我只找到了源代码,但由于我对此很陌生,所以它没有太大帮助。 有人知道一个好的教程或
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 8 年前。 Improve this ques
我想实现这样的目标: 因此,您捕获和处理的唯一内容是矩形中的区域。我需要这个,因为我想做一些 OCR 而我不想要整个屏幕。 最佳答案 也许可以帮助您这个来源,(在相机预览顶部绘制一个边界框以捕获部分图
我正在开发一个 Android 应用程序,我希望我的应用程序能够拍照并显示它们。我的问题是它制作了图片,将它存储在 SD 卡上但没有在我的应用程序中显示它,ImageView 保持空白。这是我的代码:
我正在研究 Android 相机教程,SDK 11。出于某种原因,我在 handleCameraPhoto() 中得到了一个空指针。我唯一看到的是“无法将结果 ResultInfo{who=null,
我一直在尝试实现此代码,我在其中从相机捕获图像并将其显示在我的图像查看器中,然后可以将其设置为墙纸。它在我的模拟器中运行良好,但在我的手机上,当我拍摄图像并单击“确定”时,它会强制关闭。有什么帮助吗?
我想将预览中的某些像素更改为比其余像素暗一点。假设我希望预览的上半部分比预览的下半部分暗一点。 我试图像这样使用 setPreviewCallback: camera.setPreviewCallba
我想为我的应用程序启用相机/照片库设置。我可以显示警报以编程方式启用这些吗就像应用程序启动时一样。我已附上图片以显示我希望看到我的应用程序的类似设置 对于我的应用程序,我没有看到此设置。 我的问题是这
所以我正在开发类似于相机应用程序的东西。它在原生 OpenGL 纹理上绘制实时相机预览。如果按下按钮,则会以原始形式捕获静态图像(可能比实时预览分辨率更高)。 这是我的代码的大纲。为了清楚起见,我没有
我想在我的 Android 应用程序中启动相机 Activity ,我知道该怎么做。我想问一下当相机 Activity 结束时,我如何检查它是否是用户拍摄的照片或视频? 已更新 我有一个对话框,其中询
我在横向模式下有自定义全屏摄像头。设备尺寸为 1024 x 600。 支持的预览尺寸列表 宽 x 高 176 x 144 320 x 240 352 x 288 528 x 432 640 x 480
请看下图!! 所以在这张图片中...您可以看到底部的弹出窗口,当用户“点击”“相机”按钮时,它会为用户提供 3 个选项。 那是什么观点?它是一个模态视图 Controller ,在选择一个选项时被关闭
我发布了一个应用程序,其中一项基本功能是允许用户拍照,然后将该照片保存在其外部存储上的特定文件夹中。 一切似乎都运行良好,但我现在收到两份报告,声称在拍照后单击“完成”退出相机(并返回到 Activi
我在尝试实时更换相机时遇到问题,它适用于本地视频,但远程人员看不到新相机,但仍然可以看到旧相机。我试图停止流并再次初始化,但仍然无法正常工作。这只是我的一些代码。 我到处搜索,但找不到解决方案。有人可
一个简单但非常复杂的问题:为 Flutter 相机添加点击对焦功能的最佳方法是什么? 我在整个万维网上搜索了优雅的解决方案,但一无所获。 你有想法吗? 最佳答案 我可能会迟到,但你可以试试 adv_c
我正在尝试使用 gluLookAt 方法设置 3D 相机。所以我有一个 10x10x10 的立方体,现在我想在那个立方体内移动相机。我有这样的事情: gluLookAt( camera->x,came
我赠送一个 UIImagePickerController在我的应用程序中通过在 sheet 中呈现逻辑修饰符。简而言之,以下三种类型处理显示和关闭 UIImagePickerController 的
我是一名优秀的程序员,十分优秀!