Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to discover framebuffer width on android?

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 hereenter 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 hereenter 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.

like image 716
Guilherme Torres Castro Avatar asked Mar 18 '13 01:03

Guilherme Torres Castro


1 Answers

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).

like image 111
amarullz Avatar answered Sep 20 '22 08:09

amarullz