标签: android-camera2

如何从Camera2 API连续获取帧数据用于流媒体目的?

我们正在使用Lib流媒体库开发实时视频流.Lib流媒体库支持旧的Camera api,一切正常但我们需要将Camera2 api集成到Lib流媒体库.一些功能,如使用Camera2 api的视频预览显示,我们集成但我们需要连续获取流的视频帧数据,如何获得它?请提出前进的方向.

在Lib流媒体库中,他们使用下面的帧数据​​回调方法:

mCamera.setPreviewCallback(new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            // here we get frame by frame data             
        }
    });
Run Code Online (Sandbox Code Playgroud)

streaming android android-camera2

11
推荐指数
1
解决办法
998
查看次数

Nexus 5x反向横向传感器修复在Android相机预览应用程序中

我是Android开发中的新手,所以如果我的问题很简单,我会提前道歉.在我的应用程序的一部分,我需要我的后置摄像头的实时预览,所以我创建了一个自定义类,扩展SurfaceView并实现SurfaceHolder.Callback(我基本上遵循了android文档中的说明).

不幸的是,我正在Nexus 5x中测试我的应用程序,我刚刚意识到它已经以相反的方式安装了相机传感器.出于这个原因,在我的Nexus 5x上运行时,我的应用程序的相机预览显示为颠倒,这是我不想要的.

似乎新的android.hardware.camera2 API能够自动处理这个问题.最终我需要使用这个新API更新我的所有代码,但是现在我需要的是使用旧相机API时的快速修复.

所以我在那里读书,我发现了一段代码,我需要在SurfaceChanged方法中引入以解决这个问题.这里是:

Display display = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

        if(display.getRotation() == Surface.ROTATION_0)
        {
            parameters.setPreviewSize(capHeight, capWidth);                           
            camera.setDisplayOrientation(90);
        }

        if(display.getRotation() == Surface.ROTATION_90)
        {
            parameters.setPreviewSize(capWidth, capHeight);                           
        }

        if(display.getRotation() == Surface.ROTATION_180)
        {
            parameters.setPreviewSize(capHeight, capWidth);               
        }

        if(display.getRotation() == Surface.ROTATION_270)
        {
            parameters.setPreviewSize(capWidth, capHeight);
            camera.setDisplayOrientation(180);
        }

        camera.setParameters(parameters);*/

        camera.startPreview();
Run Code Online (Sandbox Code Playgroud)

问题是我没有看到某些事情发生了变化.

有什么想法吗?

android android-camera android-view android-camera2

11
推荐指数
3
解决办法
7057
查看次数

使用Android camera2进行全屏预览

我正在使用新的camera2 API构建自定义相机.我的代码是基于谷歌提供的代码示例在这里.

我无法找到一种方法来全屏显示相机.在代码示例中,他们使用比率优化来适应所有屏幕,但它只占屏幕高度的3/4左右.

这是我的代码AutoFitTextureView:

public class AutoFitTextureView extends TextureView {

private int mRatioWidth = 0;
private int mRatioHeight = 0;

public AutoFitTextureView(Context context) {
    this(context, null);
}

public AutoFitTextureView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

/**
 * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
 * calculated from the parameters. Note …
Run Code Online (Sandbox Code Playgroud)

camera android camera2 android-camera2

11
推荐指数
2
解决办法
8717
查看次数

OpenGL/Skia 渲染 GL_TEXTURE_EXTERNAL_OES 到 GL_TEXTURE_2D

我的 OpenGL/Skia Android Camera2 应用程序遇到奇怪的问题。

我的相机将帧渲染为SurfaceTexture,这是GL_TEXTURE_EXTERNAL_OESOpenGL 中的纹理。

然后,我可以使用简单的直通着色器简单地将这个 OpenGL 纹理渲染到所有输出(1920x1080 Preview EGLSurface、4000x2000 Video Recorder )。EGLSurface

Camera --> GL_TEXTURE_EXTERNAL_OES

GL_TEXTURE_EXTERNAL_OES --> PassThroughShader --> Preview Output EGLSurface
GL_TEXTURE_EXTERNAL_OES --> PassThroughShader --> Video Recorder Output EGLSurface
Run Code Online (Sandbox Code Playgroud)

现在我想将 Skia 引入其中,它允许我在将其传递到输出之前渲染到相机框架上(例如,在框架上绘制一个红色框)。由于我无法GL_TEXTURE_EXTERNAL_OES再次直接渲染到相同的对象上,因此我创建了一个单独的离屏纹理 ( GL_TEXTURE_2D) 和一个单独的离屏帧缓冲区 (FBO1) 并附加了它们。

现在,当我渲染到 FBO1 时,屏幕外纹理GL_TEXTURE_2D会更新,然后我想将其传递GL_TEXTURE_2D到我的输出:

Camera --> GL_TEXTURE_EXTERNAL_OES
GL_TEXTURE_EXTERNAL_OES --> Skia to FBO1 + drawing a red box --> GL_TEXTURE_2D

GL_TEXTURE_2D --> PassThroughShader --> Preview Output EGLSurface
GL_TEXTURE_2D …
Run Code Online (Sandbox Code Playgroud)

c++ android opengl-es skia android-camera2

11
推荐指数
0
解决办法
500
查看次数

Camera2 ImageReader冻结重复捕获请求

我正在尝试使用camera2 API从相机捕获图像数据.我主要使用的是从android Capture2RAW示例中获取的代码.在完全停止之前,只有少数图像通过(即调用onImageAvailable).我尝试使用不同大小的RAW_SENSOR和JPEG格式捕获相同的结果.我究竟做错了什么?

this.mImageReader = ImageReader.newInstance(width, height, ImageFormat.RAW_SENSOR, /*maxImages*/ 1);
Surface surface = this.mImageReader.getSurface();
final List<Surface> surfaces = Arrays.asList(surface);
this.mCamera.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
    // Callback methods here
}, null);
CaptureRequest.Builder captureRequestBuilder;
captureRequestBuilder = this.mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
this.mCaptureRequest = captureRequestBuilder.build();
this.mCaptureSession.setRepeatingRequest(mCaptureRequest, null, null);
Run Code Online (Sandbox Code Playgroud)

android android-camera2

10
推荐指数
1
解决办法
4068
查看次数

使用Android Camera2在视频捕捉中设置亮度/对比度

我按照指南制作了一个带有Camera2 API的视频捕捉应用,

是否有以编程方式更改视频的亮度/对比度/曝光设置的规定?我正试图拍摄一些低光视频片段,我希望增加曝光率.

这里的文档似乎只适用于静态图片.

使用Camera2 API的任何这种视频捕获方式?

video android video-capture android-camera2

10
推荐指数
1
解决办法
2136
查看次数

Android上的零拷贝摄像头处理和渲染管道

我需要对实时摄像机数据(仅来自Y平面)执行CPU端只读过程,然后在GPU上进行渲染.在处理完成之前不应渲染帧(因此我并不总是希望从摄像机渲染最新帧,只是CPU端已完成处理的最新帧).渲染与相机处理分离,即使相机帧以低于此速率的速度到达,目标也是60 FPS.

在Android上有一个相关但更高级别的问题:最低开销的相机到CPU到GPU的方法

更详细地描述当前设置:我们有一个用于摄像机数据的应用程序端缓冲池,其中缓冲区是"空闲","显示"或"待处理显示".当来自摄像机的新帧到达时,我们获取一个空闲缓冲区,在那里存储帧(或者如果实际数据在某个系统提供的缓冲池中,则对它进行引用),进行处理并将结果存储在缓冲区中,然后设置缓冲区"待处理显示".在渲染器线程中,如果在渲染循环开始处有任何缓冲区"待处理显示",我们将其锁定为"显示"中的一个,渲染相机,并使用从其计算的处理信息渲染其他内容相机框架.

感谢@ fadden对上面链接的问题的回复,我现在明白了android camera2 API的"并行输出"功能在各种输出队列之间共享缓冲区,因此不应该涉及数据上的任何副本,至少在现代android上.

在评论中有一个建议,我可以同时锁定SurfaceTexture和ImageReader输出,只是"坐在缓冲区",直到处理完成.不幸的是,我不认为这适用于我的情况,因为我们仍然希望以60 FPS驱动的解耦渲染,并且仍然需要访问前一帧,同时处理新帧以确保无法获得不同步.

我想到的一个解决方案是拥有多个SurfaceTextures - 我们每个应用程序端缓冲区中都有一个(我们目前使用3个).使用该方案,当我们获得一个新的相机帧时,我们将从我们的应用程序池中获得一个空闲缓冲区.然后我们调用acquireLatestImage()ImageReader获取要处理的数据,并updateTexImage()在空闲缓冲区中调用SurfaceTexture.在渲染时我们只需要确保来自"in display"缓冲区的SufaceTexture是绑定到GL的那个,并且所有内容都应该在大多数时间同步(因为@fadden评论说在调用updateTexImage()和之间存在争用acquireLatestImage()但是时间窗口应该足够小以使其变得罕见,并且无论如何使用缓冲区中的时间戳可能是可行的和可修复的).

我注意到文档updateTexImage()只能在SurfaceTexture绑定到GL上下文时调用,这表明我在相机处理线程中也需要GL上下文,因此相机线程可以updateTexImage()在"免费"缓冲区中的SurfaceTexture上执行而渲染线程仍然能够从"显示"缓冲区中的SurfaceTexture渲染.

所以,对于问题:

  1. 这看起来是一种明智的做法吗?
  2. SurfaceTextures基本上是共享缓冲池周围的轻量包装器,还是它们消耗了一些有限的硬件资源,应该谨慎使用?
  3. SurfaceTexture调用是否足够便宜,使用多个调用仍然只是复制数据的一大胜利?
  4. 计划是否有两个线程具有不同的GL上下文,每个可能有不同的SurfaceTexture绑定,或者我要求一个痛苦的世界和错误的驱动程序?

这听起来很有希望,我会试一试; 但是,如果有人(基本上是@fadden!)知道任何我忽略的内部细节会让这个想法变得糟糕,那么我觉得值得一试.

c++ android opengl-es android-camera2

10
推荐指数
1
解决办法
1375
查看次数

是否可以将预览、图像分析和视频捕获与 CameraX 结合起来?

可以同时绑定PreviewImageAnalysis、吗?VideoCapture成对组合时,所有可能的组合(即Preview+ ImageAnalysisPreview+VideoCaptureImageAnalysis+ VideoCapture)都工作得很好,但将所有三个组合在一起会引发以下异常。

java.lang.IllegalArgumentException: No supported surface combination is found for camera device - Id : 1.  May be attempting to bind too many use cases.
    at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.getSuggestedResolutions(Camera2DeviceSurfaceManager.java:193)
    at androidx.camera.core.CameraX.calculateSuggestedResolutions(CameraX.java:943)
    at androidx.camera.core.CameraX.bindToLifecycle(CameraX.java:293)
    at androidx.camera.lifecycle.ProcessCameraProvider.bindToLifecycle(ProcessCameraProvider.java:229)
Run Code Online (Sandbox Code Playgroud)

是否有任何解决方法可以让我使用ImageAnalysis并同时录制视频?

android android-camera2 android-camerax

10
推荐指数
1
解决办法
2691
查看次数

旋转的 Android CameraX 图像

我已经按照 Google CameraX代码实验室来实现自定义相机。相机预览很好,但是当我在旋转图像捕获图像后拍摄图像时。我正在以纵向模式拍摄图像,但保存的图像是横向的。这是配置相机的方法

private fun startCamera() {

    val cameraProviderFuture = ProcessCameraProvider.getInstance(this)

    cameraProviderFuture.addListener(Runnable {
        // Used to bind the lifecycle of cameras to the lifecycle owner
        val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

        // Preview
        val preview = Preview.Builder()
            .setTargetRotation(this.windowManager.defaultDisplay.rotation)
            .build()
            .also {
                it.setSurfaceProvider(viewFinder.createSurfaceProvider())
            }

        imageCapture = ImageCapture.Builder()
            .setTargetRotation(this.windowManager.defaultDisplay.rotation)
            .build()

        val imageAnalyzer = ImageAnalysis.Builder()
            .build()
            .also {
                it.setAnalyzer(cameraExecutor, LuminosityAnalyzer { luma ->
                    Log.d(TAG, "Average luminosity: $luma")
                })
            }

        // Select back camera as a default
        val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

        try { …
Run Code Online (Sandbox Code Playgroud)

android image-rotation android-orientation android-camera2 android-camerax

10
推荐指数
2
解决办法
3212
查看次数

Camera2 将图像从 ImageReader 传递到 MediaRecorder

我正在尝试创建一个CameraCaptureSession具有四个输出的 Camera2:

  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)
Run Code Online (Sandbox Code Playgroud)

..进入SurfaceMediaRecorder

val surface = MediaCodec.createPersistentInputSurface()
val recorder = MediaRecorder(context)
..
recorder.setInputSurface(surface)
Run Code Online (Sandbox Code Playgroud)

我想我可能需要一个带有直通着色器的 OpenGL 管道 - 但我不知道如何从ImageReader …

android opengl-es surfaceview android-camera android-camera2

10
推荐指数
1
解决办法
514
查看次数