LReader Reference Manual & Media Probing Guide
The LReader class is the high-performance media analysis and metadata probing engine of the now2sdk framework. It utilizes FFmpeg's libavformat and libavcodec header interfaces to inspect media files, parse demuxer headers, and resolve stream parameters.
Because LReader only reads header context packets without decoding raw video or audio payload frames, it executes almost instantaneously. It is designed to safely run inside worker threads to populate media playlists, validate resolution standards, and extract start/end timecodes.
1. Probing & Extraction Architecture
graph TD
A[Media File Path] -->|LReader::open| B(avformat_open_input)
B -->|Demuxer Header Check| C(avformat_find_stream_info)
C -->|Stream Registration| D{Best Streams Discovery}
D -->|AVMEDIA_TYPE_VIDEO| E[Video Stream Index]
D -->|AVMEDIA_TYPE_AUDIO| F[Audio Stream Index]
E --> G[Codec Descriptor / Pixel Format]
F --> H[Codec Parameters / Channel Layout]
G --> I[Width, Height, FPS, Scan Type, Chroma, Bit Depth]
H --> J[Audio Codec, Bitrate, Channels]
C --> K[Format Context Duration & global metadata]
K --> L[Timecode Track Parsing]
Key Capabilities:
- Zero-Decode Metadata Parsing: Reads structural metadata packets in milliseconds by bypassing the heavy frame decompression and YUV/RGB color conversion pipelines.
- Scan Type Classification: Checks the video codec parameters'
field_orderproperty to distinguish progressive streams from interlaced formats. - Pixel and Chroma Subsampling Resolution: Queries pixel descriptors to resolve chroma subsampling configuration (e.g.
4:2:0,4:2:2,4:4:4) and color channel depths (e.g.,8-bit,10-bit,12-bit). - Drop-Frame and Non-Drop-Frame Timecode Arithmetic: Parses initial starting SMPTE timecode string fields from metadata dictionaries, recalculating the final output timecode boundaries dynamically based on duration and frame rate.
2. API Reference & Public Methods
All public methods available in the LReader class:
📌 Session Control Methods
bool open(const std::string& filePath);
Initializes the container demuxer context and analyzes all available stream headers. Returns true if successful, false if the file is corrupted, inaccessible, or has an unsupported container.
void close();
Closes open format contexts, releases demuxer resource descriptors, and resets internal stream indexes. Called automatically inside the destructor.
📌 Metadata Retrieval Registry
Since LReader is a read-only metadata prober, it has no setProps configuration key-value registry. Instead, properties are queried directly using the query methods detailed below:
| Method | Return Type | Default Fallback | Description |
|---|---|---|---|
getDurationMs() |
double |
0 |
Returns the total duration of the media file in milliseconds. |
getFps() |
double |
0 |
Returns the average frame rate of the video stream. |
getWidth() |
int |
0 |
Returns the width of the video track in pixels. |
getHeight() |
int |
0 |
Returns the height of the video track in pixels. |
getFileLen() |
long long |
0 |
Returns the file size in bytes using local filesystem statistics. |
getVideoCodec() |
std::string |
"N/A" |
Returns the video codec name (e.g., "h264", "hevc", "prores", "dnxhd"). |
getAudioCodec() |
std::string |
"N/A" |
Returns the audio codec name (e.g., "aac", "mp3", "pcm_s16le"). |
getContainer() |
std::string |
"Unknown" |
Returns the format container name (e.g., "mov,mp4,m4a,3gp,3g2", "matroska,webm", "mpegts"). |
getBitrate() |
long long |
0 |
Returns the total bitrate of the file context in bits per second (bps). |
getAudioBitrate() |
long long |
0 |
Returns the bitrate of the audio stream in bits per second (bps). |
getAudioChannels() |
int |
0 |
Returns the number of audio channels (e.g. 2 for Stereo, 6 for 5.1). |
getAspectRatio() |
std::string |
"N/A" |
Returns the display aspect ratio (DAR) formatted string (e.g., "16:9", "4:3"). |
getColorSpace() |
std::string |
"N/A" |
Returns the color space name (e.g., "bt709", "bt2020nc", "smpte170m"). |
getChromaSubsampling() |
std::string |
"N/A" |
Returns the pixel subsampling scheme (e.g., "4:2:0", "4:2:2", "4:4:4"). |
getBitDepth() |
int |
8 |
Returns the color depth per pixel channel (e.g., 8, 10, 12). |
getScanType() |
std::string |
"N/A" |
Returns the frame scanning type ("Progressive" or "Interlaced"). |
getInPoint() |
double |
0 |
Returns the initial in-point of the playback timeline in ms (always 0). |
getOutPoint() |
double |
getDurationMs() |
Returns the end boundary point of the playback timeline in ms. |
getInTC() |
std::string |
"00:00:00:00" |
Returns the starting SMPTE timecode read from file/stream metadata blocks. |
getOutTC() |
std::string |
"00:00:00:00" |
Calculates and returns the end SMPTE timecode (Start Timecode + Duration). |
3. Integration Code Example
This example (adapted from the Playout Example mainwindow.cpp) demonstrates how to asynchronously probe a media file dropped into a playlist widget using LReader inside a worker pool to prevent UI thread blocking.
#include <QThreadPool>
#include <QFileInfo>
#include "LReader.h"
#include <iostream>
void addFileToPlaylist(const std::string& filePath) {
// Start asynchronous execution task in thread pool
QThreadPool::globalInstance()->start([filePath]() {
QFileInfo fi(QString::fromStdString(filePath));
if (!fi.exists()) {
std::cerr << "File does not exist: " << filePath << std::endl;
return;
}
// Initialize media prober
LReader probe;
if (probe.open(filePath)) {
// Retrieve metadata parameters
double durationMs = probe.getDurationMs();
double frameRate = probe.getFps();
int width = probe.getWidth();
int height = probe.getHeight();
long long fileLen = probe.getFileLen();
std::string vCodec = probe.getVideoCodec();
std::string aCodec = probe.getAudioCodec();
std::string container = probe.getContainer();
std::string chroma = probe.getChromaSubsampling();
int bitDepth = probe.getBitDepth();
std::string scan = probe.getScanType(); // "Progressive" or "Interlaced"
std::string inTC = probe.getInTC();
std::string outTC = probe.getOutTC();
// Print summary
std::cout << "Successfully probed: " << fi.fileName().toStdString() << "\n"
<< " Container: " << container << " | File Size: " << fileLen << " bytes\n"
<< " Resolution: " << width << "x" << height << " (" << scan << ")\n"
<< " Frame Rate: " << frameRate << " FPS\n"
<< " Codecs: Video: " << vCodec << " (" << chroma << ", " << bitDepth << "-bit) | Audio: " << aCodec << "\n"
<< " Duration: " << durationMs << " ms\n"
<< " SMPTE Ranges: " << inTC << " --> " << outTC << std::endl;
// Clean up demuxer context
probe.close();
} else {
std::cerr << "FFmpeg failed to open or parse metadata for: " << filePath << std::endl;
}
});
}