Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

GStreamer video capture

Linear: AUT-102

Spawns gst-launch-1.0 with a videotestsrc-fed pipeline that emits raw BGRA frames on stdout, then chunks the byte stream into VideoFrames — the same type decode::VideoStream returns.

3 seconds of videotestsrc SMPTE colorbars at 320×240, 30 fps. Same content GstreamerVideoCapture::test_source emits frame-by-frame into a VideoFrame stream; the animated ball in the bottom-left corner is videotestsrc's built-in "is this actually moving" indicator. Captured directly via gst-launch-1.0 + x264enc + mp4mux (see just snapshots-media-video) so the chapter carries a concrete artifact independent of the Rust test path.

api

Pipeline

videotestsrc is-live=false
  ! videoconvert
  ! video/x-raw,format=BGRA,width=W,height=H,framerate=F/1
  ! fdsink fd=1

videotestsrc's default pattern is SMPTE colorbars with a tiny animated ball — successive frames carry different bytes, which makes visual smoke checks cheap.

AUT-102 only covers the videotestsrc path. M-MEDIA.16 (live webcam) will add an autovideosrc variant; M-MEDIA.17 (playback harness) will add a filesrc ! decodebin variant that decodes the existing crates/decode/tests/fixtures/sample.mp4.

Quick start

#![allow(unused)]
fn main() {
use media::gstreamer_video::GstreamerVideoCapture;

let mut cap = GstreamerVideoCapture::test_source(640, 360, 30)?;
for _ in 0..30 {
    let frame = cap.next_frame()?;
    println!(
        "frame {} pts={:.4}s {}×{} bgra-bytes={}",
        frame.frame_index,
        frame.pts_seconds,
        frame.width,
        frame.height,
        frame.bgra.len(),
    );
}
Ok::<(), media::gstreamer_video::Error>(())
}

Lifecycle

Drop kills the child + waits. Same pattern as gstreamer_audio and decode::GstreamerPipeStream — a dropped pipe without an explicit kill keeps the gst-launch process decoding into the void.

PTS

PTS is computed from frame_index / framerate via MediaTime::from_frame. At 30 fps, frame 90's PTS is exactly 3.0 s — no rounding drift across long captures (the rounding in MediaTime's sample/frame helpers ensures the integer round-trip stays tight).

Integration tests

3 tests in crates/media/tests/gstreamer_video_integration.rs, all skip-guarded via media::gstreamer::is_available:

TestAsserts
emits_frames_with_expected_dimensions_and_pts5 frames, correct dimensions, byte length, frame index, contiguous PTS.
frames_have_distinct_content_smpte_colorbarsFrame 0 vs frame 16 differ in many bytes (animated SMPTE ball moves).
dimensions_and_framerate_round_trip_through_capturedimensions() + framerate() accessors match construction args.