Ask Your Question
0

How to write/display video frame into /dev/fb1 with open('/dev/fb1', 'rb+')?

asked 2018-12-02 01:48:40 -0600

vivpatel99 gravatar image

I am trying to write a video frame into Linux framebuffer fb1. My code is

cap = cv2.VideoCapture(0)
while cap.is_Opened():
    ret, frame = cap.read()
    with open('/dev/fb1', 'rb+') as buf:
       buf.write(frame)
cap.release()

so now i can display my video frame on framebuffer fb1, but is not clean please see the output video frame in below picture. I am also open to suggestion if any better(or efficient) way to do it.

  1. I already used mmap.mmap to write into the frame buffer 1, but it is giving me the same output.
  2. I also tried using os.environ['SDL_FBDEV'] = '/dev/fb1' in a different thread so that i can use two framebuffers at a same time. (here I can get a clear image but I can use only one framebuffer which I do not want to do)
  3. I have also tried converting video frame into bytearray()

enter image description here

this is my one of the ideas to solve my problem working with two framebuffers simultaneously. the black area will be used for display GUI by framebuffer 0 by os.environ['SDL_FBDEV'] = '/dev/fb0'for more information please see my old question https://stackoverflow.com/questions/5...

Thank you in advanced

edit retag flag offensive close merge delete

Comments

1

you should try to find out the required pixel format for your framebuffer (from here it looks, like it expects 32bit instead of the 24bits, that come from the VideoCapture)

frame32 = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)

might help

berak gravatar imageberak ( 2018-12-02 08:52:06 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2018-12-03 04:11:08 -0600

kbarni gravatar image

Other than the pixel format (as suggested by @berak) you also need to consider the size of the framebuffer. If you write the raw data, it won't jump to new line at the second row of the image.

One solution would be to resize the image to the framebuffer size, and copy it to the framebuffer. It will give a full-screen image.

ret, frame = cap.read()
frame32 = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)
fbframe = cv2.resize(frame32, (1920,1080))
with open('/dev/fb1', 'rb+') as buf:
   buf.write(fbframe)

The second solution is to fill the rest of every line with black pixels:

ret, frame = cap.read()
frame32 = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)
lineend=np.zeros(stride-4*frame.cols)
with open('/dev/fb1', 'rb+') as buf:
   for row in frame32:
      buf.write(row)
      buf.write(lineend)

Probably you'll have to combine the two solutions; the first won't work well if the ratio of the image side is not the same as your screen; the second will still be problematic if the image is larger than the framebuffer.

You can get the framebuffer resolution from the /sys/class/graphics/fb0/modes file, and the stride from the /sys/class/graphics/fb0/stride file.

The code above is untested, so it might have bugs and need adjustments.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2018-12-02 01:48:40 -0600

Seen: 5,762 times

Last updated: Dec 03 '18