Overview
This guide walks through the complete implementation of a GStreamer-based object detection application using Qualcomm hardware-accelerated plugins. The application:- Reads an H.264-encoded MP4 file from disk
- Performs YOLOv8 object detection using a TFLite inference pipeline
- Overlays detection bounding boxes and labels onto video frames
- Renders the annotated output to a Wayland display
The complete application source code is available in the repository. For foundational concepts — including pipeline construction, state management, caps negotiation, bus handling, and dynamic pads — refer to Building a Native GStreamer Application.
Pipeline Diagram

Implementation Steps
1
Step 1 — Define the Application Context
The application consolidates all runtime state into a single context structure:
This pattern avoids global variables, keeps application state self-contained, and simplifies callback implementations that require access to pipeline objects.
2
Step 2 — Create the Pipeline Object
GstPipeline object is created using gst_pipeline_new(), establishing the top-level container that owns and manages all elements added to it.As a GstBin subclass, it is responsible for:- Element lifecycle management
- State propagation across all contained elements
- Synchronization of clocks and timing
3
Step 3 — Instantiate Pipeline Elements
gst_element_factory_make(). The first argument identifies the element by its factory name; the second assigns a unique instance name (retrievable later via gst_bin_get_by_name()).4
Step 4 — Configure Elements
Before the pipeline starts, element properties are set to define runtime behavior.Input source — configure AI inference — configure
filesrc with the path to the input file:qtimlvideotflitebin with delegate, post-processing module, model, and labels:Display sink — configure
waylandsink for synchronized, full-screen rendering:5
Step 5 — Add Elements to the Pipeline
gst_bin_add_many() transfers ownership of all elements to the pipeline, making it responsible for their lifecycle — including state transitions and resource cleanup. At this point, elements share the same execution context but are not yet connected.6
Step 6 — Link Static Pipeline Elements
The link between
qtdemux and h264parse is intentionally omitted here. qtdemux exposes its output pads dynamically at runtime — this connection is established in Step 7 via dynamic pad handling.7
Step 7 — Handle Dynamic Pads (Demuxer)
qtdemux determines the number and type of elementary streams only after parsing input data, dynamically creating output pads for each discovered stream. Since these pads do not exist at construction time, they cannot be linked statically.A callback is registered for the pad-added signal on the demuxer:h264parse if it carries an H.264 video stream — all other stream types (e.g., audio) are ignored:8
Step 8 — Set Up Bus Message Handling
The application retrieves the pipeline bus and registers callbacks for error, EOS, and warning messages:
9
Step 9 — Handle Ctrl+C (Interrupt Signal)
A The signal handler checks the current pipeline state and responds accordingly:
SIGINT handler is registered using g_unix_signal_add() to route the OS signal safely into the GLib main loop:Sending EOS before stopping is particularly important for file-based outputs where finalization steps (e.g., writing file headers/footers) must complete.
10
Step 10 — Start the Pipeline
READY and PAUSED states before reaching PLAYING, at which point data begins to flow from filesrc through to waylandsink.11
Step 11 — Run the Main Loop
- Blocks the main thread for the duration of pipeline execution
- Dispatches bus messages and invokes registered callbacks as events occur
- Exits only when explicitly quit by the EOS callback, error handler, or interrupt signal handler
12
Step 12 — Handle End-of-Stream
When the pipeline processes the last buffer and EOS propagates to the sink, an EOS bus message is delivered to the registered callback:The callback quits the main loop, allowing the main thread to resume and proceed with pipeline teardown and resource cleanup.
13
Step 13 — Handle Errors
If a fatal error occurs at any stage of pipeline execution, the error callback is invoked:Errors are treated as fatal. The callback:
- Logs the error message and debug information for diagnostics
- Quits the main loop to initiate controlled shutdown
- The application subsequently transitions the pipeline to
NULLand releases all resources
14
Step 14 — Teardown and Resource Cleanup
Once the main loop exits — whether due to EOS, error, or interrupt — the application performs an orderly teardown:
This sequence ensures all resources are released in the correct order and that the application exits in a well-defined, clean state.

