LSignal Reference Manual & Test Signal Generator Guide
The LSignal class is the background video signal generator of the now2sdk framework, derived from the LObject base class. It is designed to act as a fallback program source or test generator that continuously yields video frames at a precise target frame rate.
LSignal can generate:
- Solid Color Frames: Generated mathematically using BT.601 RGB-to-YUV color conversion space mappings.
- Static Test Pattern Slides: Loaded, decoded, and scaled from local image files (PNG, JPG, BMP).
To minimize CPU usage, generated frames are cached in memory (m_cachedFrame) and cloned on subsequent cycles rather than being re-generated or re-decoded.
1. Mathematical & Decoded Generation Pipeline
graph TD
A[LSignal Start] --> B{Source Type?}
B -->|setColor hex| C[1. Parse hex R G B values]
C --> D[2. Convert using BT.601 YUV formulas]
D --> E[3. Allocate YUV420P AVFrame & fill Y, U, V buffers]
B -->|setImage path| F[1. Open image using avformat]
F --> G[2. Decode image frame to AVFrame]
G --> H[3. Scale and convert to YUV420P using SwsContext]
H --> E
E --> I[Clone frame to m_cachedFrame cache]
J[signalLoop Thread] -->|At precise frame durations| K[Clone m_cachedFrame]
K --> L[Call distributeVideoFrame to Sinks]
YUV Color Conversion Formula
For solid colors, LSignal converts RGB colors from hexadecimal string values to YUV420p space using standard BT.601 formulas:
$Y = 0.299R + 0.587G + 0.114B$
$U = -0.1687R - 0.3313G + 0.5B + 128$
$V = 0.5R - 0.4187G - 0.0813B + 128$
2. API Reference & Public Methods
All public methods available in the LSignal class:
📌 Generator Control & Initializations
LSignal();
Constructor. Sets the default video format to 720p50 (vF_HD720_50p) and background color to black ("#000000").
virtual ~LSignal();
Destructor. Stops the background thread loop and releases cached frame resources.
bool Start();
Spawns the background generator thread (signalLoop) to begin distributing frames to downstream sinks.
void Stop();
Stops the background thread loop and cleans up memory buffers.
📌 Properties Setup Methods
Since LSignal is a lightweight signal generator, it does not implement a setProps(key, value) dictionary interface. Instead, settings are configured directly using the following type-safe C++ methods:
| Method | Parameters / Types | Description |
|---|---|---|
setColor(hex) |
const std::string& hex |
Sets the solid color value (e.g. "#0000FF" for blue). Clears any loaded image path and resets the frame cache. |
setImage(path) |
const std::string& path |
Loads a local image path (PNG, JPG, BMP). Clears the solid color and resets the frame cache. |
setVideoFormat(props) |
const videoFormatProps& props |
Configures the target resolution and frame rate. If standard standard enums are set, it automatically resolves physical resolutions and FPS before resetting the frame cache. |
getVideoFormat(props) |
videoFormatProps& props |
Populates the output structure with the current target specifications. |
3. Ingestion Fallback Integration Example
The following example demonstrates how to set up LSignal as a backup "No Signal" blue screen or custom slide in a vision mixing pipeline. If the main camera capture feed fails or disconnects, the pipeline automatically routes the generator's frames to the program output.
#include "LLive.h"
#include "LSignal.h"
#include "LPreview.h"
#include "LOutput.h"
#include <iostream>
class FallbackBroadcaster {
public:
FallbackBroadcaster()
: m_liveInput(new LLive()),
m_backupSignal(new LSignal()),
m_preview(new LPreview())
{
// 1. Configure standard video standard properties (1080p50)
videoFormatProps format;
format.setVideoFormat = vF::HD1080_50p;
// 2. Configure Backup Signal Generator
m_backupSignal->setVideoFormat(format);
// Option A: Solid Blue screen background
m_backupSignal->setColor("#000080");
// Option B: Custom slide image (uncomment to use)
// m_backupSignal->setImage("/var/broadcasting/images/no_signal_slide.png");
m_backupSignal->Start(); // Start generating backup frames
// 3. Configure Camera Live capture
m_liveInput->setProps("device_type", "decklink");
m_liveInput->DeviceSet(0);
m_liveInput->setVideoFormat(format);
m_liveInput->Start();
// 4. Bind preview screen and listen to live camera
m_preview->previewEnable(nullptr, true, true);
m_preview->previewObject(m_liveInput);
}
~FallbackBroadcaster() {
m_liveInput->Stop();
m_backupSignal->Stop();
delete m_preview;
delete m_backupSignal;
delete m_liveInput;
}
// Dynamic pipeline routing triggered by signal watchdog check
void verifySignalWatchdog() {
bool cameraDisconnected = m_liveInput->noSignalGet();
if (cameraDisconnected) {
std::cout << "[Watchdog] Camera signal lost! Routing fallback test signal..." << std::endl;
// Route preview and output lines to backup signal generator
m_preview->previewObject(m_backupSignal);
} else {
// Restore live camera feed
m_preview->previewObject(m_liveInput);
}
}
private:
LLive* m_liveInput;
LSignal* m_backupSignal;
LPreview* m_preview;
};