videocore – Support for playing video sources
This module provides the video pipeline shared between video sources and
video outputs. It is the video equivalent of the audiocore module.
Video sources, such as mipicsi.Camera, implement the internal videosource
protocol. A VideoBuffer tells a video source where to put its frames in a
framebuffer, such as mipidsi.Display, and can move it as needed.
Stream a MIPI CSI camera live into the board’s display (a MIPI DSI panel on ESP32-P4-Function-EV, for example):
import board
import displayio
import mipicsi
import sc2336
import videocore
display = board.DISPLAY()
framebuffer = display.framebuffer
sensor = sc2336.SC2336(board.I2C())
sensor.mode = sc2336.Mode.HD_1280x720_RAW10_30FPS
# Trim the sensor output to the display size.
sensor.width = display.width
sensor.height = display.height
camera = mipicsi.Camera(sensor, output_format=mipicsi.PixelFormat.RGB565)
video = videocore.VideoBuffer(framebuffer)
video.play(camera)
root = displayio.Group()
root.append(video)
display.root_group = root
Capture a smaller part of the sensor’s image into a bytearray and let
displayio place it in a Group, together with other layers. displayio bulk
copies new frames into the group’s area of the display (no color
conversion):
import board
import displayio
import mipicsi
import sc2336
import videocore
sensor = sc2336.SC2336(board.I2C())
sensor.mode = sc2336.Mode.VGA_640x480_RAW10_50FPS
# Trim the sensor output to a 320x240 window.
sensor.width = 320
sensor.height = 240
camera = mipicsi.Camera(sensor, output_format=mipicsi.PixelFormat.RGB565)
capture = videocore.VideoBuffer(bytearray(320 * 240 * 2))
capture.play(camera)
root = displayio.Group()
root.append(capture)
capture.x = 350 # position of the live video within the group
capture.y = 180
board.DISPLAY().root_group = root # live video joins the displayio scene
Available on these boards
- class videocore.VideoBuffer(framebuffer: circuitpython_typing.FrameBuffer | circuitpython_typing.WriteableBuffer)
Stream a video source into a framebuffer or buffer.
A VideoBuffer connects a video source, such as
mipicsi.Camera, to a target: either a framebuffer, such asmipidsi.Display, or a writable buffer such as abytearray. It is the video counterpart ofaudioio.AudioOut.Add a VideoBuffer to a
displayio.Groupto show it on a display. A framebuffer target only streams while it is shown.Implementations may restrict size and position. For example, on ESP32-P4 a framebuffer target must be full width because the DMA can’t skip between rows without an intermediate buffer. Setting an unsupported position directly raises an error, but moving a containing Group may give garbled output instead.
When the target is a plain buffer, frames are written compactly (row stride equals
width * bits_per_pixel / 8) and can be read from Python at any time, for example to process or save camera pixels.See the
videocoremodule overview for complete examples.Create a VideoBuffer that plays video into the given framebuffer
- Parameters:
framebuffer – The framebuffer to copy video frames into, or a writable buffer such as a
bytearrayormemoryview.
- play(source: circuitpython_typing.VideoSource) None
Begin streaming the given video source into the target.
The source streams continuously, writing each new frame where the VideoBuffer tells it to, replacing the previous one. The source’s frame format must be byte aligned. The source’s size and format are then fixed for the duration of the
play(); sources that change them requirestop()and a newplay().When the target is a framebuffer, its bits per pixel must match the framebuffer color depth and the whole frame must fit within the framebuffer at the current
x/yposition. An exception may be raised if the video can’t be played directly into the framebuffer.When the target is a plain buffer, it must be large enough for a whole frame.
- Parameters:
source (VideoSource) – The video source to play, such as
mipicsi.Camera
- source: circuitpython_typing.VideoSource | None
The video source being played, or None when not playing. (read-only)
- x: int
The x position of the video within its Group. Framebuffer targets only support
x == 0and raiseValueErrorotherwise.
- __enter__() VideoBuffer
No-op used by Context Managers.
- __exit__() None
Automatically deinitializes the hardware when exiting a context. See Lifetime and ContextManagers for more info.