How to stream a video from webcam to hdmi out, using only base overlay of PYNQ-Z1?

Can you please provide me with a simple python code to capture video from USB-webcam , and pass it on to HDMI out ( to a monitor) ?

I tried a lot to do the same . But it didn’t work out. Thanks in advance .

You should be able to achieve this by combining what you find in the usb_webcam and hdmi_video_pipeline notebooks that should be already available on your PYNQ SD card image.

1 Like

Hi Giuseppe ,
Thank you for your kind response . I’m writing here the code snippets I’m using , in order to stream the video from HDMI in/Webcam to HDMI out .

Case 1 : Tying the HDMI in to HDMI out

from pynq.overlays.base import BaseOverlay
from pynq.lib.video import *

base = BaseOverlay(“base.bit”)
hdmi_in = base.video.hdmi_in
hdmi_out = base.video.hdmi_out

hdmi_in.configure()
hdmi_out.configure(hdmi_in.mode)

hdmi_in.start()
hdmi_out.start()

hdmi_in.tie(hdmi_out)

Issue faced : I’ve played a video in the laptop , and connected the HDMI out of laptop to the HDMI in port of PYNQ-Z1 . But no video is displayed in the monitor . The screen is blinking . But no error is thrown after running this code .

Case 2 : Tying the Webcam input to HDMI out

from pynq.overlays.base import BaseOverlay
from pynq.lib.video import *
base = BaseOverlay(“base.bit”)

Mode = VideoMode(640,480,24)
hdmi_out = base.video.hdmi_out
hdmi_out.configure(Mode,PIXEL_BGR)
hdmi_out.start()

monitor (output) frame buffer size

frame_out_w = 1920
frame_out_h = 1080

camera (input) configuration

frame_in_w = 640
frame_in_h = 480

initialize camera from OpenCV

import cv2

videoIn = cv2.VideoCapture(0)
videoIn.set(cv2.CAP_PROP_FRAME_WIDTH, frame_in_w);
videoIn.set(cv2.CAP_PROP_FRAME_HEIGHT, frame_in_h);
print("Capture device is open: " + str(videoIn.isOpened()))

import numpy as np

ret, frame = videoIn.read()
hdmi_out.writeframe(frame)

Issue faced : AttributeError: ‘numpy.ndarray’ object has no attribute ‘flush’
The webcam gets turned on , but ,again , no video is displayed .

Case 3 : Streaming video from HDMI in to HDMI out , as par hdmi_video_pipeline notebook

Code :

from pynq.overlays.base import BaseOverlay
from pynq.lib.video import *
base = BaseOverlay(“base.bit”)

hdmi_in = base.video.hdmi_in
hdmiin_frontend = base.video.hdmi_in.frontend
hdmiin_frontend.start()
print("HDMI in frontend mode is " , hdmiin_frontend.mode)

colorspace_in = base.video.hdmi_in.color_convert
print("colorspace_in is " , colorspace_in)
bgr2rgb = [0, 0, 1,
0, 1, 0,
1, 0, 0,
0, 0, 0]
print("bgr2rgb matrix is " , bgr2rgb)

colorspace_in.colorspace = bgr2rgb

pixel_in = base.video.hdmi_in.pixel_pack
pixel_in.bits_per_pixel = 8
print("Bits per input pixel is " , pixel_in.bits_per_pixel)

inputmode = hdmiin_frontend.mode
print("input mode is " , inputmode)
framemode = VideoMode(inputmode.width, inputmode.height, 8)
print("framemode is " , framemode)

vdma = base.video.axi_vdma
vdma.readchannel.mode = framemode
print("vdma readchannel mode is " , vdma.readchannel.mode)

print(“I was just testing”)
vdma.writechannel.mode = framemode
print("vdma writechannel mode is " , vdma.writechannel.mode)

#hdmi_in.cacheable_frames = False
#vdma.readchannel.start()
#vdma.writechannel.start()

#frame = vdma.readchannel.readframe()
#vdma.writechannel.writeframe(frame)
#frame.freebuffer()
#vdma.readchannel.tie(vdma.writechannel)

hdmi_out = base.video.hdmi_out
pixel_out = base.video.hdmi_out.pixel_unpack
pixel_out.bits_per_pixel = 8
colorspace_out = base.video.hdmi_out.color_convert
colorspace_out.colorspace = bgr2rgb

hdmiout_frontend = base.video.hdmi_out.frontend
hdmiout_frontend.mode = hdmiin_frontend.mode
print("HDMI out frontend mode is " , hdmiout_frontend.mode)
hdmiout_frontend.start()

vdma.readchannel.start()
vdma.writechannel.start()

frame = vdma.readchannel.readframe()
vdma.writechannel.writeframe(frame)

Output :

HDMI in frontend mode is VideoMode: width=1920 height=1080 bpp=24
colorspace_in is <pynq.lib.video.pipeline.ColorConverter object at 0xaebe56b0>
bgr2rgb matrix is [0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0]
Bits per input pixel is 8
input mode is VideoMode: width=1920 height=1080 bpp=24
framemode is VideoMode: width=1920 height=1080 bpp=8
vdma readchannel mode is VideoMode: width=1920 height=1080 bpp=8
I was just testing
vdma writechannel mode is VideoMode: width=1920 height=1080 bpp=8
HDMI out frontend mode is VideoMode: width=1920 height=1080 bpp=24

Please help . Please have a look at the above code segments , and kindly guide me in solving the issues .

Hi @ayan1305, first of all, I gotta say the layout of the post does not make things easy for me. It’s pretty unreadable. Next time please share a GIST or enclose the code in code snippets.

Case 1: make sure that in the display settings of your laptop, the display corresponding to the Z1 is enabled. Make sure you can output frames to the output monitor by simply writing a monochromatic frame to the HDMI out (simply create a new frame and give a constant value through range assignment frame[:] = 42)

Case 2: You need to convert the frame read from videoIn.read() into a PYNQ bufffer so it will be compatible with the video subsystem.

outframe = hdmi_out.newframe()
outframe[:] = frame
hdmi_out.writeframe(frame)

Case 3: not really clear what is your problem here.

Hi, Mr. Ayan ! Did you found solution for your problem, Like I’m facing same problem as you mentioned.

Thanks @gnatale
I guess you mean:

hdmi_out.writeframe(outframe)