use std::time::Duration;
use broadcast_common::impl_spec_display;
use crate::error::Unsupported;
use crate::timing::utc_timing::UtcScheme;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum PresentationType {
#[default]
Static,
Dynamic,
}
impl PresentationType {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::Static => "static",
Self::Dynamic => "dynamic",
}
}
}
impl_spec_display!(PresentationType);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum Actuate {
OnLoad,
#[default]
OnRequest,
}
impl Actuate {
#[must_use]
pub fn name(&self) -> &'static str {
match self {
Self::OnLoad => "onLoad",
Self::OnRequest => "onRequest",
}
}
}
impl_spec_display!(Actuate);
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct Xlink {
pub href: String,
pub actuate: Actuate,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub struct ByteRange {
pub first: u64,
pub last: Option<u64>,
}
impl ByteRange {
#[must_use]
pub fn new(first: u64, last: u64) -> Self {
Self {
first,
last: Some(last),
}
}
#[must_use]
pub fn len(&self) -> Option<u64> {
let last = self.last?;
last.checked_sub(self.first)?.checked_add(1)
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len().is_none()
}
pub fn offset_len(&self) -> Result<(u64, u64), Unsupported> {
self.len()
.map(|n| (self.first, n))
.ok_or(Unsupported::OpenEndedRange)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[non_exhaustive]
pub struct UrlType {
pub source_url: Option<String>,
pub range: Option<ByteRange>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[non_exhaustive]
pub struct BaseUrl {
pub url: String,
pub service_location: Option<String>,
pub priority: Option<u32>,
pub weight: Option<u32>,
pub availability_time_offset: Option<f64>,
pub availability_time_complete: Option<bool>,
pub time_shift_buffer_depth: Option<Duration>,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[non_exhaustive]
pub struct Descriptor {
pub scheme_id_uri: String,
pub value: Option<String>,
pub id: Option<String>,
pub default_kid: Option<String>,
pub url_query: Option<UrlQueryInfo>,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[non_exhaustive]
pub struct UrlQueryInfo {
pub use_mpd_url_query: bool,
pub query_string: Option<String>,
pub query_template: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct UtcTiming {
pub scheme: UtcScheme,
pub scheme_id_uri: String,
pub value: String,
pub id: Option<String>,
}
impl UtcTiming {
pub fn values(&self) -> impl Iterator<Item = &str> {
self.value.split_ascii_whitespace()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
pub struct MpdFeatures {
pub patch_location: bool,
pub event_stream: bool,
pub inband_event_stream: bool,
pub preselection: bool,
pub service_description: bool,
pub producer_reference_time: bool,
pub content_steering: bool,
pub resync: bool,
pub low_latency: bool,
pub xlink_resolve_to_zero: bool,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[non_exhaustive]
pub struct CommonAttributes {
pub profiles: Option<String>,
pub width: Option<u32>,
pub height: Option<u32>,
pub sar: Option<String>,
pub frame_rate: Option<String>,
pub audio_sampling_rate: Option<String>,
pub mime_type: Option<String>,
pub codecs: Option<String>,
pub max_playout_rate: Option<f64>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[non_exhaustive]
pub struct BaseInfo {
pub timescale: Option<u64>,
pub presentation_time_offset: Option<u64>,
pub ept_delta: Option<i64>,
pub pd_delta: Option<i64>,
pub presentation_duration: Option<u64>,
pub time_shift_buffer_depth: Option<Duration>,
pub index_range: Option<ByteRange>,
pub index_range_exact: Option<bool>,
pub availability_time_offset: Option<f64>,
pub availability_time_complete: Option<bool>,
pub initialization: Option<UrlType>,
pub representation_index: Option<UrlType>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[non_exhaustive]
pub struct SegmentBase {
pub info: BaseInfo,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub struct TimelineEntry {
pub t: Option<u64>,
pub n: Option<u64>,
pub d: u64,
pub r: i64,
pub k: Option<u64>,
}
impl TimelineEntry {
#[must_use]
pub fn new(d: u64) -> Self {
Self {
t: None,
n: None,
d,
r: 0,
k: None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[non_exhaustive]
pub struct SegmentTimeline {
pub entries: Vec<TimelineEntry>,
pub unsupported: Option<Unsupported>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[non_exhaustive]
pub struct MultiInfo {
pub base: BaseInfo,
pub duration: Option<u64>,
pub start_number: Option<u64>,
pub end_number: Option<u64>,
pub timeline: Option<SegmentTimeline>,
pub bitstream_switching: Option<UrlType>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[non_exhaustive]
pub struct SegmentTemplate {
pub multi: MultiInfo,
pub media: Option<String>,
pub index: Option<String>,
pub initialization: Option<String>,
pub bitstream_switching: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[non_exhaustive]
pub struct SegmentUrl {
pub media: Option<String>,
pub media_range: Option<ByteRange>,
pub index: Option<String>,
pub index_range: Option<ByteRange>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[non_exhaustive]
pub struct SegmentList {
pub multi: MultiInfo,
pub xlink: Option<Xlink>,
pub urls: Vec<SegmentUrl>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[non_exhaustive]
pub struct SegmentLayer {
pub base: Option<SegmentBase>,
pub list: Option<SegmentList>,
pub template: Option<SegmentTemplate>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[non_exhaustive]
pub struct Representation {
pub id: String,
pub bandwidth: u64,
pub quality_ranking: Option<u32>,
pub dependency_ids: Vec<String>,
pub common: CommonAttributes,
pub base_urls: Vec<BaseUrl>,
pub segment: SegmentLayer,
pub content_protections: Vec<Descriptor>,
pub essential_properties: Vec<Descriptor>,
pub supplemental_properties: Vec<Descriptor>,
pub audio_channel_configurations: Vec<Descriptor>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[non_exhaustive]
pub struct AdaptationSet {
pub id: Option<u64>,
pub group: Option<u64>,
pub lang: Option<String>,
pub content_type: Option<String>,
pub par: Option<String>,
pub segment_alignment: bool,
pub start_with_sap: Option<u8>,
pub bitstream_switching: Option<bool>,
pub common: CommonAttributes,
pub xlink: Option<Xlink>,
pub roles: Vec<Descriptor>,
pub accessibilities: Vec<Descriptor>,
pub labels: Vec<String>,
pub base_urls: Vec<BaseUrl>,
pub segment: SegmentLayer,
pub content_protections: Vec<Descriptor>,
pub essential_properties: Vec<Descriptor>,
pub supplemental_properties: Vec<Descriptor>,
pub audio_channel_configurations: Vec<Descriptor>,
pub representations: Vec<Representation>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[non_exhaustive]
pub struct Period {
pub id: Option<String>,
pub start: Option<Duration>,
pub duration: Option<Duration>,
pub bitstream_switching: bool,
pub xlink: Option<Xlink>,
pub base_urls: Vec<BaseUrl>,
pub segment: SegmentLayer,
pub asset_identifier: Option<Descriptor>,
pub essential_properties: Vec<Descriptor>,
pub supplemental_properties: Vec<Descriptor>,
pub adaptation_sets: Vec<AdaptationSet>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[non_exhaustive]
pub struct Mpd {
pub id: Option<String>,
pub profiles: Vec<String>,
pub kind: PresentationType,
pub availability_start_time_us: Option<i64>,
pub availability_end_time_us: Option<i64>,
pub publish_time_us: Option<i64>,
pub media_presentation_duration: Option<Duration>,
pub minimum_update_period: Option<Duration>,
pub min_buffer_time: Option<Duration>,
pub time_shift_buffer_depth: Option<Duration>,
pub suggested_presentation_delay: Option<Duration>,
pub max_segment_duration: Option<Duration>,
pub max_subsegment_duration: Option<Duration>,
pub base_urls: Vec<BaseUrl>,
pub locations: Vec<String>,
pub utc_timings: Vec<UtcTiming>,
pub essential_properties: Vec<Descriptor>,
pub supplemental_properties: Vec<Descriptor>,
pub periods: Vec<Period>,
pub features: MpdFeatures,
}