Looks like there is a support for getting 4 channel format into OpenCV via VideoCapture but when trying to use VideoWriter I get an error:
write frame skipped - expected CV_8UC3
import numpy as np
import time
# Settings
DEVICE = "/dev/video0"
WIDTH = 1920
HEIGHT = 1080
FPS = 60
OUTPUT_FILE = "output_hw_test.mp4"
# ---------------------------------------------------------
# 1. CAPTURE PIPELINE (GPU De-tiling)
# ---------------------------------------------------------
# Logic:
# v4l2src -> UYVY (Camera)
# vapostproc -> BGRA (GPU VRAM) - Heavy Math happens here
# vapostproc -> BGRA (System RAM) - Hardware Download/De-tiling
# appsink -> Python (4-channel Numpy Array)
# ---------------------------------------------------------
cap_pipeline = (
f"v4l2src device={DEVICE} ! "
f"video/x-raw,width={WIDTH},height={HEIGHT},format=UYVY,framerate={FPS}/1 ! "
"vapostproc ! "
"video/x-raw(memory:VAMemory),format=BGRA ! "
"vapostproc ! "
"video/x-raw,format=BGRA ! "
"appsink drop=true max-buffers=1"
)
# ---------------------------------------------------------
# 2. WRITER PIPELINE (Hardware Encoding)
# ---------------------------------------------------------
# Logic:
# appsrc -> BGRA (From Python)
# vapostproc -> NV12 (GPU VRAM) - Upload & Format Conversion
# vah265enc -> H.265 (Hardware Encode)
# filesink -> MP4 File
# ---------------------------------------------------------
writer_pipeline = (
"appsrc ! "
f"video/x-raw,format=BGR,width={WIDTH},height={HEIGHT},framerate={FPS}/1 ! "
"videoconvert ! " # <--- MANDATORY: Bridges BGR to Hardware
"video/x-raw,format=NV12 ! " # Convert to NV12 (Best for Encoders)
"vapostproc ! " # Uploads NV12 to GPU
"vah265enc ! " # Hardware Encoding
"h265parse ! "
"mp4mux ! "
f"filesink location={OUTPUT_FILE}"
)
print(f"Opening Capture: {DEVICE} @ {WIDTH}x{HEIGHT} {FPS}fps...")
cap = cv2.VideoCapture(cap_pipeline, cv2.CAP_GSTREAMER)
if not cap.isOpened():
print("Error: Could not open capture pipeline.")
exit()
print(f"Opening Writer: {OUTPUT_FILE}...")
# 0 = FourCC (Let GStreamer handle it), FPS, Resolution
out = cv2.VideoWriter(writer_pipeline, cv2.CAP_GSTREAMER, 0, float(FPS), (WIDTH, HEIGHT))
if not out.isOpened():
print("Error: Could not open writer pipeline.")
cap.release()
exit()
print("Recording... Press 'q' to stop (or Ctrl+C in terminal)")
frame_count = 0
start_time = time.time()
try:
while True:
ret, frame = cap.read()
if not ret:
print("Error: Failed to receive frame.")
break
# -------------------------------------------------
# CRITICAL CHECK
# -------------------------------------------------
# frame.shape should be (1080, 1920, 4) because we asked for BGRA
# out.write() expects this exact shape because writer_pipeline says format=BGRA
# -------------------------------------------------
# Write the 4-channel BGRA frame directly
out.write(frame)
frame_count += 1
# Optional: Calculate FPS every 60 frames
if frame_count % 60 == 0:
elapsed = time.time() - start_time
print(f"Encoding FPS: {frame_count / elapsed:.2f}", end="\r")
# Optional: Show Preview
# We need to slice to BGR just for imshow (imshow doesn't always like 4 channels)
# This view is cheap (no copy)
# cv2.imshow("Preview", frame[:, :, :3])
# if cv2.waitKey(1) & 0xFF == ord('q'):
# break
except KeyboardInterrupt:
print("\nStopping...")
finally:
print(f"\nClosing resources. Recorded {frame_count} frames.")
cap.release()
out.release()
cv2.destroyAllWindows()
Describe the feature and motivation
After looking at this code, looks like there is not support for the VideoWriter function for 4 channel format (ie BGRA)
https://github.com/opencv/opencv/blob/4.x/modules/videoio/src/cap_gstreamer.cpp
Looks like there is a support for getting 4 channel format into OpenCV via VideoCapture but when trying to use VideoWriter I get an error:
write frame skipped - expected CV_8UC3
this is my test_pipeline.py script:
Additional context
No response