【问题标题】:Trying to get max fps from Android Camera尝试从 Android 相机获取最大 fps
【发布时间】:2014-06-24 10:50:32
【问题描述】:

我正在开发一个 Android 应用程序,我需要从相机获取最大 fps。

我一直在尝试实现 setPreviewCallbackWithBuffer,但无法正常工作。

谁能给我一个例子或解释?

我设置了一个计时器,每 10 毫秒运行一次,然后我运行 takePicture()。这是正确的,或者获得最大 fps 的方法是什么?

我已经到处搜索了,但找不到适合我的解释。

谢谢。

编辑 2:

startRecording.setOnClickListener( new View.OnClickListener() {
public void onClick(View v) {
    if(!recording)
    {
        recording = true;
        thread.start();

        cam.startPreview();     
        Size previewSize=cam.getParameters().getPreviewSize();
        int dataBufferSize=(int)(previewSize.height*previewSize.width*(ImageFormat.getBitsPerPixel(cam.getParameters().getPreviewFormat())/8.0));

        cam.addCallbackBuffer(new byte[dataBufferSize]);
        cam.addCallbackBuffer(new byte[dataBufferSize]);
        cam.addCallbackBuffer(new byte[dataBufferSize]);
        cam.setPreviewCallbackWithBuffer(new PreviewCallback() {
            public void onPreviewFrame(byte[] imageData, Camera arg1) {
                try {
                    photos.add(imageData);
                } catch(Exception e) {                                                                  System.out.println("ERROR!");
                }

            }
        });
    }
(...)

谢谢!

【问题讨论】:

  • 请完整而准确地解释“我无法让它工作”的含义。 “对吗?”——不。
  • @CommonsWare 我刚刚在主题中添加了代码和一些注释。你现在能明白吗?谢谢!

标签: android camera buffer frame-rate


【解决方案1】:

问题 #1:计时器

引用the documentation for setPreviewCallbackWithBuffer():

除了在屏幕上显示它们之外,还使用 ​​addCallbackBuffer(byte[]) 提供的缓冲区安装要为每个预览帧调用的回调。只要预览处于活动状态并且缓冲区可用,就会重复调用回调。任何其他预览回调都会被覆盖。

所以,删除你的Timer。调用一次setPreviewCallbackWithBuffer(),您将被调用预览帧,因为它们已准备好进行处理。

问题 #2:硬编码缓冲区大小

引用the documentation for addCallbackBuffer():

对于 YV12 以外的格式,缓冲区的大小是通过将预览图像的宽度、高度和每个像素的字节数相乘来确定的。宽度和高度可以从 getPreviewSize() 中读取。可以使用 getPreviewFormat() 中的图像格式从 getBitsPerPixel(int) / 8 计算每个像素的字节数。

如果使用 YV12 格式,则可以使用 setPreviewFormat(int) 中列出的公式计算大小。

请遵循这些说明,而不是猜测缓冲区大小。

问题 #3:添加缓冲区

进一步引用the documentation for addCallbackBuffer()

将预分配的缓冲区添加到预览回调缓冲区队列。应用程序可以将一个或多个缓冲区添加到队列中。当预览帧到达并且仍有至少一个可用缓冲区时,该缓冲区将被使用并从队列中删除。然后使用缓冲区调用预览回调。如果一帧到达并且没有剩余缓冲区,则丢弃该帧。应用程序在处理完其中的数据后应将缓冲区添加回来。

当您调用setPreviewCallbackWithBuffer() 时,请先调用addCallbackBuffer() 以获得一些缓冲区。在onPreviewFrame() 中,安排一个后台线程来处理该帧的缓冲区。完成该工作后,通过调用 addCallbackBuffer() 将相同的缓冲区添加回池中。 只是继续分配新的缓冲区。

【讨论】:

  • 我编辑了主题并将代码更改为我现在所拥有的,按照您所说的。我的问题是如何获得更多捕获?实际上我只得到3个捕获。另一个问题是为什么我保存的照片全黑?您说过“完成该工作后,通过调用 addCallbackBuffer() 将相同的缓冲区添加回池中”。我怎样才能做到这一点?我无法理解。非常感谢!!
  • @user2989493:您似乎错过了问题 3 的大部分建议。 photos.add() 似乎并没有在后台线程上工作。当后台线程工作完成时,我看不到您通过addCallbackBuffer() 将处理后的缓冲区添加回池的位置。
  • 我将 byte[] 添加到 ArrayList,然后“线程”完成工作(将 byte[] 保存到位图)。这是错误的做法吗?关于 addCallbackBuffer() 我不明白我是怎么做到的。你能解释一下吗?谢谢!!
  • @user2989493:“这是错误的方法吗?” - 因为我没有看到代码,所以我无法回答。然而,这听起来并不好,因为多个线程不能在同一个ArrayList 上工作(使用其他东西,比如LinkedBlockingQueue)。 “关于 addCallbackBuffer() 我不明白我是怎么做到的”——你声称有一个线程。该线程正在运行一些代码来处理byte[]。完成该代码后,您要做的最后一件事是调用 addCallbackBuffer()byte[] 添加回缓冲区池。
  • 现在我可以达到 25 fps 左右。问题是保存的照片是黑色图像。你有提示吗,或者你需要我发布代码?非常感谢 !! ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-30
  • 2022-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多