5

我正在我的 android 设备上捕获帧缓冲区,但解码不适用于正确的分辨率。

我发现我可以使用以下方法获得 bbp 和屏幕分辨率:

ioctl -rl 28 /dev/graphics/fb0 17920

此命令返回:

返回缓冲区:f0 00 00 00 40 01 00 00 f0 00 00 00 80 02 00 00 00 00 00 00 00 00 00 00 20 00 00 00

在 little-endian 格式中,我有:

  • 最后四个字节 (20) 是 bbp 32的数量。
  • 前四个字节是屏幕宽度 0xF0 = 240
  • 字节 5 到 8 是屏幕高度 0x0140 = 320

我尝试使用以下命令解码 fb(Galaxy 5):

./ffmpeg -vcodec rawvideo -f rawvideo -pix_fmt rgb32 -s 240x320 -i fb0 -f image2 -vcodec png image%d.png

我收到了这个警告:

缓冲区大小无效,数据包大小 40960 < 预期长度 307200 解码流 #0:0 时出错:参数无效

这两张图片:

在此处输入图像描述 在此处输入图像描述

我的原始文件有 655.360 字节,但预期的正确值是 614.400 字节,使用以下公式:

文件大小 = xres * yres * bpp/8 * numberOfFrames

fileSize = 240 * 320 * 32/8 * 2 (android 使用双帧缓冲) = 614.400

令我惊讶的是,我将 ffmpeg 上的宽度大小更改为 256 以匹配 655.360 字节并工作(有点,右侧有 16 个额外像素!我得到以下图像:

在此处输入图像描述 在此处输入图像描述

所以我的问题是,如果我的屏幕分辨率为 240,为什么我必须使用 256 宽度。以及如何为其他分辨率发现这个神奇的数字。

4

1 回答 1

7

您应该使用line_length来计算线的大小。

+-------------------------+----+
|                         |    |
|                         |    | 
|<-------- XRES --------->|    | = Xres is display resolution
|                         |    |
|                         |    |
|<------- LINE LENGTH -------->| = Memory Size per line
|                         |    |
|                         |    |
+-------------------------+----+
                      ^      ^
                      |      |
  display on screen --+      +----> This is stride

右边的填充被称为“步幅”(步幅=(以像素为单位的线长度)-宽度)。如果显示分辨率不是 8 的倍数,许多设备在帧缓冲区中都有这个步幅。

所以公式是:

fileSize = line_length * yres * numberOfFrames

不要将它与 bpp/8 相乘,因为 line_length 是内存大小(不是像素大小)。

要检索line_length您应该使用FBIOGET_FSCREENINFO (0x4602 - 17922) 而不是FBIOGET_VSCREENINFO (0x4600 - 17922),如下所示:

ioctl -rl 50 /dev/graphics/fb0 17922

我的 Galaxy Nexus 像这样返回:

return buf: 6f 6d 61 70 66 62 00 00 00 00 00 00 00 00 00 00 00 00 a0 ac 00 00 00
01 00 00 00 00 00 00 00 00 02 00 00 00 01 00 01 00 00 00 00 00 80 0b 00 00 00 00
                                                               ^_________^

我的 Galaxy Nexus 有 line_length: 2944 (0xb80)。

于 2013-08-18T00:12:19.577 回答