5

i'm capturing framebuffer on my android device, but the decode is not working for the correctly resolution.

I found i can get the bbp and screen resoution using:

ioctl -rl 28 /dev/graphics/fb0 17920

This command return:

return buf: 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

In little-endian format i have:

  • The last four bytes (20) is the number of bbp 32.
  • The first four bytes is the screen width 0xF0 = 240
  • Bytes 5 to 8 is the screen height 0x0140 = 320

I tried to decode the fb (Galaxy 5) using the folowing command :

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

And i got this warning:

Invalid buffer size, packet size 40960 < expected length 307200 Error while decoding stream #0:0: Invalid argument

and this two images:

enter image description here enter image description here

My raw file have 655.360 bytes but the correctly value expected is 614.400 bytes using this equation:

fileSize = xres * yres * bpp/8 * numberOfFrames

fileSize = 240 * 320 * 32/8 * 2 (android use double framebuffer) = 614.400

For my surprise i change width size on ffmpeg to 256 to match 655.360 bytes and worked (kind of, there are 16 extras pxs on the right side! I got the following images:

enter image description here enter image description here

So my question is WHY i have to use 256 width if my screen resolution is 240. And how to discovery this magic number for others resolutions.

Community
  • 1
  • 1
Guilherme Torres Castro
  • 15,135
  • 7
  • 59
  • 96
  • I found the same issue on my LG400 (Android 2.3.6). Strange thing is that the monitor tool (android-sdk/tools/monitor) takes a good 256px wide screenshot. So I'm guessing this monitor tool knows how to determine the real framebuffer width, but I still haven't found how. – Giacomo Apr 08 '13 at 12:28

1 Answers1

7

You should used line_length to calculate size of line.

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

The right padding is called "stride" (stride = (line_length in pixel) - width). Many device had this stride in the framebuffer if the display resolution is not multiply of 8.

So the formula is:

fileSize = line_length * yres * numberOfFrames

Don't multiply it with bpp/8, because the line_length is memory size (not pixel size).

To retrive the line_length You should used FBIOGET_FSCREENINFO (0x4602 - 17922) rather than FBIOGET_VSCREENINFO (0x4600 - 17922) like this:

ioctl -rl 50 /dev/graphics/fb0 17922

My Galaxy Nexus return like this:

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
                                                               ^_________^

My Galaxy Nexus have line_length: 2944 (0xb80).

amarullz
  • 346
  • 4
  • 4