pub mod core;
pub mod error;
pub mod filter;
pub mod format;
pub mod frame;
pub mod graph;
pub mod log;
pub mod metadata;
pub mod plugin_abi;
pub mod plugin_host;
pub mod render;
pub mod scheduler;
pub mod source;
pub mod y4m;
pub use core::{Core, CoreConfig};
pub use error::{ErrorCategory, ErrorCode, PixelFlowError, Result};
pub use filter::{
FilterDescriptor, FilterOptionValue, FilterOptions, FilterPlan, FilterPlanRequest,
FilterPlanner, FilterRegistry,
};
pub use format::{
ChromaSiting, ChromaSubsampling, ColorMatrix, ColorPrimaries, ColorRange, ColorTransfer,
FormatDescriptor, FormatFamily, PlaneDescriptor, PlaneRole, SampleType, format_with_bit_depth,
resolve_format_alias,
};
pub use frame::{
AllocatorConfig, Frame, FrameBuilder, Plane, PlaneMut, PlaneRows, RawPlane, RawPlaneMut, Sample,
};
pub use graph::{
Clip, ClipFormat, ClipMedia, ClipResolution, FilterChangeSet, FilterCompatibility, FrameCount,
FrameRate, Graph, GraphBuilder, GraphNode, NodeId, NodeKind, ValidatedGraph, ValidationPlan,
is_y4m_compatible_format,
};
pub use log::{LogLevel, LogRecord, LogSink, Logger, NoopLogSink};
pub use metadata::{Metadata, MetadataKind, MetadataSchema, MetadataValue, Rational};
pub use plugin_abi::{
PIXELFLOW_ABI_VERSION, PIXELFLOW_PLUGIN_ENTRY_SYMBOL, PixelflowErrorCategory,
PixelflowFilterDescriptorV1, PixelflowHostApiV1, PixelflowMetadataKind, PixelflowPluginApiV1,
PixelflowPluginEntryV1, PixelflowRegistrar, PixelflowStatus, PixelflowStringView,
};
pub use plugin_host::{
LoadedPlugin, is_dynamic_library, load_plugins_from_directories, platform_plugin_directories,
};
pub use render::{
FrameExecutor, FrameRequest, OrderedRender, RenderEngine, RenderExecutorMap, RenderOptions,
RenderRange,
};
pub use scheduler::{
ConcurrencyClass, DependencyPattern, DynamicDependencyBounds, FilterTiming, SourceCapabilities,
TimingReport, WorkerPoolConfig,
};
pub use source::{SourceOptionValue, SourceRequest};
pub use y4m::{Y4mWriter, y4m_chroma_tag};
#[must_use]
pub const fn version() -> &'static str {
env!("CARGO_PKG_VERSION")
}
#[cfg(test)]
mod tests {
#![expect(clippy::indexing_slicing, reason = "allow in tests")]
use std::sync::{Arc, Mutex};
use super::{
AllocatorConfig, ErrorCategory, ErrorCode, LogLevel, LogRecord, LogSink, Logger,
MetadataSchema, PixelFlowError, resolve_format_alias,
};
#[test]
fn version_matches_package_version() {
assert_eq!(super::version(), env!("CARGO_PKG_VERSION"));
}
#[test]
fn structured_error_preserves_category_code_and_message() {
let error = PixelFlowError::new(
ErrorCategory::Graph,
ErrorCode::new("graph.cycle"),
"graph contains a cycle",
);
assert_eq!(error.category(), ErrorCategory::Graph);
assert_eq!(error.code().as_str(), "graph.cycle");
assert_eq!(error.message(), "graph contains a cycle");
assert_eq!(
error.to_string(),
"graph error graph.cycle: graph contains a cycle"
);
}
#[test]
fn logger_forwards_records_to_sink() {
#[derive(Default)]
struct RecordingSink {
records: Mutex<Vec<LogRecord>>,
}
impl LogSink for RecordingSink {
fn log(&self, record: &LogRecord) {
self.records
.lock()
.expect("record lock poisoned")
.push(record.clone());
}
}
let sink = Arc::new(RecordingSink::default());
let logger = Logger::new(sink.clone());
logger.log(LogLevel::Warn, "pixelflow_core::tests", "cache disabled");
let records = sink.records.lock().expect("record lock poisoned");
assert_eq!(records.len(), 1);
assert_eq!(records[0].level(), LogLevel::Warn);
assert_eq!(records[0].target(), "pixelflow_core::tests");
assert_eq!(records[0].message(), "cache disabled");
}
#[test]
fn default_logger_discards_records() {
let logger = Logger::default();
logger.log(LogLevel::Info, "pixelflow_core::tests", "startup");
}
#[test]
fn public_modules_are_reachable() {
let format = resolve_format_alias("yuv420p10").expect("format alias should resolve");
let schema = MetadataSchema::core();
let allocator = AllocatorConfig::default();
let media = super::ClipMedia::fixed(
format.clone(),
1920,
1080,
24,
super::Rational {
numerator: 24_000,
denominator: 1_001,
},
);
assert_eq!(format.name(), "yuv420p10");
assert!(schema.contains_key("core:matrix"));
assert!(allocator.actual_alignment() >= 64);
assert!(super::is_y4m_compatible_format(&format));
assert!(matches!(media.frame_count(), super::FrameCount::Finite(24)));
assert_eq!(super::ColorMatrix::Bt709.as_str(), "bt709");
assert_eq!(super::ColorTransfer::Pq.as_str(), "pq");
assert_eq!(super::ColorPrimaries::DisplayP3.as_str(), "display_p3");
assert_eq!(super::ChromaSiting::Center.offsets(), (0.5, 0.5));
}
}