diff --git a/event/src/event.rs b/event/src/event.rs index 7fef8a7..48b051c 100644 --- a/event/src/event.rs +++ b/event/src/event.rs @@ -1,5 +1,8 @@ use core::fmt; -use mem::{smpte::TimecodeInstant, str::StaticString}; +use mem::{ + smpte::{TimecodeInstant, TimecodeProperties}, + str::StaticString, +}; /// Conditional VLT requirement to perform a [EventDescription::JumpEvent]. #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -204,6 +207,8 @@ pub enum EventDescription { TimecodeEvent { /// Timecode Instant this LTC starts at time: TimecodeInstant, + /// Timecode properties + properties: TimecodeProperties, }, /// Marks the point where SMPTE LTC should stop running diff --git a/event/src/eventcursor.rs b/event/src/eventcursor.rs index 4c3be6c..a41f8be 100644 --- a/event/src/eventcursor.rs +++ b/event/src/eventcursor.rs @@ -106,6 +106,7 @@ mod tests { f: 0, frame_progress: 0, }, + properties: mem::smpte::TimecodeProperties::default(), }), }, ); diff --git a/mem/src/lib.rs b/mem/src/lib.rs index 5459548..12a45e4 100644 --- a/mem/src/lib.rs +++ b/mem/src/lib.rs @@ -23,4 +23,6 @@ pub mod time; /// Low level data types for SMPTE Timecode pub mod smpte { pub use super::timecode::TimecodeInstant; + pub use super::timecode::TimecodeProperties; + pub use super::timecode::TimecodeUserBitFormat; } diff --git a/mem/src/timecode.rs b/mem/src/timecode.rs index 253db92..d98048c 100644 --- a/mem/src/timecode.rs +++ b/mem/src/timecode.rs @@ -1,5 +1,45 @@ use core::fmt::{Display, Formatter, Result}; +/// SMPTE timecode properties +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)] +pub struct TimecodeProperties { + /// If set to true, frame numbers 0 and 1 are skipped during the first second of every minute, except multiples + /// of 10 minutes. This converts 30 frames/second time code to the 29.97 frames/second NTSC + /// standard. (from Wikipedia, "Linear timecode") + pub drop_frame: bool, + /// Set to true if the time code is synchronized to a color video signal. The frame number modulo + /// 2 (for NTSC and SECAM) or modulo 4 (for PAL) should be preserved across cuts in order to + /// avoid phase jumps in the chrominance subcarrier. (from Wikipedia, "Linear timecode") + pub color_framing: bool, + /// Binary group flag; user bit format + pub user_bit_format: TimecodeUserBitFormat, + /// Indicates that the time code is synchronized to an external clock. False indicates the time + /// origin is arbitrary. In practice, this means "ignore the timestamp in an LTC event, and run + /// LTC from device time instead". + pub use_wall_time: bool, + /// 32 user bits + pub user_bits: [u8; 4], + /// Frame number offset + pub frame_offset: u8, +} + +/// SMPTE BFG, binary group flag. +/// Indicates the format of user bits +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Default, Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)] +pub enum TimecodeUserBitFormat { + /// No (or unspecified) format + #[default] + Unspecified = 0, + /// Date and timezone, according to SMPTE 309M + DateTimezone = 1, + /// Four 8-bit characters, transmitted little-endian + EightBitLittleEndian = 2, + /// Reserved and unused + Reserved11 = 3, +} + /// A SMPTE LTC timestamp, including frame rate. #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Default, Debug, Clone, Copy, Eq)]