mirror of
https://github.com/sile/hls_m3u8.git
synced 2024-11-25 08:31:00 +00:00
improvments to ExtXStart
This commit is contained in:
parent
9273e6c16c
commit
6ef8182f2c
3 changed files with 118 additions and 149 deletions
|
@ -103,11 +103,12 @@ impl MasterPlaylist {
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use hls_m3u8::MasterPlaylist;
|
||||
/// use hls_m3u8::tags::ExtXStart;
|
||||
/// use hls_m3u8::MasterPlaylist;
|
||||
/// use hls_m3u8::types::Float;
|
||||
///
|
||||
/// MasterPlaylist::builder()
|
||||
/// .start(ExtXStart::new(20.123456))
|
||||
/// .start(ExtXStart::new(Float::new(20.3)))
|
||||
/// .build()?;
|
||||
/// # Ok::<(), Box<dyn ::std::error::Error>>(())
|
||||
/// ```
|
||||
|
|
|
@ -326,53 +326,70 @@ impl fmt::Display for ExtXDateRange {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::types::Float;
|
||||
use chrono::offset::TimeZone;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
const HOURS_IN_SECS: i32 = 3600; // 1 hour = 3600 seconds
|
||||
|
||||
#[test]
|
||||
fn test_parser() {
|
||||
assert_eq!(
|
||||
"#EXT-X-DATERANGE:\
|
||||
ID=\"splice-6FFFFFF0\",\
|
||||
START-DATE=\"2014-03-05T11:15:00Z\",\
|
||||
PLANNED-DURATION=59.993,\
|
||||
SCTE35-OUT=0xFC002F0000000000FF000014056F\
|
||||
FFFFF000E011622DCAFF000052636200000000000\
|
||||
A0008029896F50000008700000000"
|
||||
macro_rules! generate_tests {
|
||||
( $( { $left:expr, $right:expr } ),* $(,)* ) => {
|
||||
#[test]
|
||||
fn test_display() {
|
||||
$(
|
||||
assert_eq!($left.to_string(), $right.to_string());
|
||||
)*
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parser() {
|
||||
$(
|
||||
assert_eq!($left, $right.parse().unwrap());
|
||||
)*
|
||||
assert!("#EXT-X-DATERANGE:END-ON-NEXT=NO"
|
||||
.parse::<ExtXDateRange>()
|
||||
.is_err());
|
||||
|
||||
assert!("garbage".parse::<ExtXDateRange>().is_err());
|
||||
assert!("".parse::<ExtXDateRange>().is_err());
|
||||
|
||||
assert!(concat!(
|
||||
"#EXT-X-DATERANGE:",
|
||||
"ID=\"test_id\",",
|
||||
"START-DATE=\"2014-03-05T11:15:00Z\",",
|
||||
"END-ON-NEXT=YES"
|
||||
)
|
||||
.parse::<ExtXDateRange>()
|
||||
.unwrap(),
|
||||
.is_err());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generate_tests! {
|
||||
{
|
||||
ExtXDateRange::builder()
|
||||
.id("splice-6FFFFFF0")
|
||||
.start_date(FixedOffset::east(0).ymd(2014, 3, 5).and_hms(11, 15, 0))
|
||||
.planned_duration(Duration::from_secs_f64(59.993))
|
||||
.scte35_out(
|
||||
"0xFC002F0000000000FF00001\
|
||||
4056FFFFFF000E011622DCAFF0\
|
||||
00052636200000000000A00080\
|
||||
29896F50000008700000000"
|
||||
)
|
||||
.scte35_out(concat!(
|
||||
"0xFC002F0000000000FF00001",
|
||||
"4056FFFFFF000E011622DCAFF0",
|
||||
"00052636200000000000A00080",
|
||||
"29896F50000008700000000"
|
||||
))
|
||||
.build()
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
"#EXT-X-DATERANGE:\
|
||||
ID=\"test_id\",\
|
||||
CLASS=\"test_class\",\
|
||||
START-DATE=\"2014-03-05T11:15:00Z\",\
|
||||
END-DATE=\"2014-03-05T11:16:00Z\",\
|
||||
DURATION=60.1,\
|
||||
PLANNED-DURATION=59.993,\
|
||||
X-CUSTOM=45.3,\
|
||||
SCTE35-CMD=0xFC002F0000000000FF2,\
|
||||
SCTE35-OUT=0xFC002F0000000000FF0,\
|
||||
SCTE35-IN=0xFC002F0000000000FF1,\
|
||||
END-ON-NEXT=YES,\
|
||||
UNKNOWN=PHANTOM"
|
||||
.parse::<ExtXDateRange>()
|
||||
.unwrap(),
|
||||
concat!(
|
||||
"#EXT-X-DATERANGE:",
|
||||
"ID=\"splice-6FFFFFF0\",",
|
||||
"START-DATE=\"2014-03-05T11:15:00Z\",",
|
||||
"PLANNED-DURATION=59.993,",
|
||||
"SCTE35-OUT=0xFC002F0000000000FF000014056F",
|
||||
"FFFFF000E011622DCAFF000052636200000000000",
|
||||
"A0008029896F50000008700000000"
|
||||
)
|
||||
},
|
||||
{
|
||||
ExtXDateRange::builder()
|
||||
.id("test_id")
|
||||
.class("test_class")
|
||||
|
@ -380,61 +397,28 @@ mod test {
|
|||
.end_date(FixedOffset::east(0).ymd(2014, 3, 5).and_hms(11, 16, 0))
|
||||
.duration(Duration::from_secs_f64(60.1))
|
||||
.planned_duration(Duration::from_secs_f64(59.993))
|
||||
.insert_client_attribute("X-CUSTOM", 45.3)
|
||||
.insert_client_attribute("X-CUSTOM", Float::new(45.3))
|
||||
.scte35_cmd("0xFC002F0000000000FF2")
|
||||
.scte35_out("0xFC002F0000000000FF0")
|
||||
.scte35_in("0xFC002F0000000000FF1")
|
||||
.end_on_next(true)
|
||||
.build()
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
assert!("#EXT-X-DATERANGE:END-ON-NEXT=NO"
|
||||
.parse::<ExtXDateRange>()
|
||||
.is_err());
|
||||
|
||||
assert!("garbage".parse::<ExtXDateRange>().is_err());
|
||||
assert!("".parse::<ExtXDateRange>().is_err());
|
||||
|
||||
assert!("#EXT-X-DATERANGE:\
|
||||
ID=\"test_id\",\
|
||||
START-DATE=\"2014-03-05T11:15:00Z\",\
|
||||
END-ON-NEXT=YES"
|
||||
.parse::<ExtXDateRange>()
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_display() {
|
||||
assert_eq!(
|
||||
ExtXDateRange::builder()
|
||||
.id("test_id")
|
||||
.class("test_class")
|
||||
.start_date(FixedOffset::east(0).ymd(2014, 3, 5).and_hms(11, 15, 0))
|
||||
.end_date(FixedOffset::east(0).ymd(2014, 3, 5).and_hms(11, 16, 0))
|
||||
.duration(Duration::from_secs_f64(60.1))
|
||||
.planned_duration(Duration::from_secs_f64(59.993))
|
||||
.insert_client_attribute("X-CUSTOM", 45.3)
|
||||
.scte35_cmd("0xFC002F0000000000FF2")
|
||||
.scte35_out("0xFC002F0000000000FF0")
|
||||
.scte35_in("0xFC002F0000000000FF1")
|
||||
.end_on_next(true)
|
||||
.build()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"#EXT-X-DATERANGE:\
|
||||
ID=\"test_id\",\
|
||||
CLASS=\"test_class\",\
|
||||
START-DATE=\"2014-03-05T11:15:00Z\",\
|
||||
END-DATE=\"2014-03-05T11:16:00Z\",\
|
||||
DURATION=60.1,\
|
||||
PLANNED-DURATION=59.993,\
|
||||
SCTE35-CMD=0xFC002F0000000000FF2,\
|
||||
SCTE35-OUT=0xFC002F0000000000FF0,\
|
||||
SCTE35-IN=0xFC002F0000000000FF1,\
|
||||
X-CUSTOM=45.3,\
|
||||
END-ON-NEXT=YES"
|
||||
)
|
||||
.unwrap(),
|
||||
concat!(
|
||||
"#EXT-X-DATERANGE:",
|
||||
"ID=\"test_id\",",
|
||||
"CLASS=\"test_class\",",
|
||||
"START-DATE=\"2014-03-05T11:15:00Z\",",
|
||||
"END-DATE=\"2014-03-05T11:16:00Z\",",
|
||||
"DURATION=60.1,",
|
||||
"PLANNED-DURATION=59.993,",
|
||||
"SCTE35-CMD=0xFC002F0000000000FF2,",
|
||||
"SCTE35-OUT=0xFC002F0000000000FF0,",
|
||||
"SCTE35-IN=0xFC002F0000000000FF1,",
|
||||
"X-CUSTOM=45.3,",
|
||||
"END-ON-NEXT=YES"
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -8,22 +8,42 @@ use crate::types::{Float, ProtocolVersion};
|
|||
use crate::utils::{parse_yes_or_no, tag};
|
||||
use crate::{Error, RequiredVersion};
|
||||
|
||||
/// # [4.3.5.2. EXT-X-START]
|
||||
/// This tag indicates a preferred point at which to start
|
||||
/// playing a Playlist.
|
||||
///
|
||||
/// [4.3.5.2. EXT-X-START]: https://tools.ietf.org/html/rfc8216#section-4.3.5.2
|
||||
/// By default, clients should start playback at this point when beginning a
|
||||
/// playback session.
|
||||
#[derive(ShortHand, PartialOrd, Debug, Clone, Copy, PartialEq)]
|
||||
#[shorthand(enable(must_use))]
|
||||
pub struct ExtXStart {
|
||||
#[shorthand(enable(skip))]
|
||||
time_offset: Float,
|
||||
/// Returns whether clients should not render media stream whose
|
||||
/// presentation times are prior to the specified time offset.
|
||||
/// The time offset of the [`MediaSegment`]s in the playlist.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use hls_m3u8::tags::ExtXStart;
|
||||
/// let mut start = ExtXStart::new(20.123456);
|
||||
/// use hls_m3u8::types::Float;
|
||||
///
|
||||
/// let mut start = ExtXStart::new(Float::new(20.123456));
|
||||
/// # assert_eq!(start.time_offset(), Float::new(20.123456));
|
||||
///
|
||||
/// start.set_time_offset(Float::new(1.0));
|
||||
/// assert_eq!(start.time_offset(), Float::new(1.0));
|
||||
/// ```
|
||||
///
|
||||
/// [`MediaSegment`]: crate::MediaSegment
|
||||
#[shorthand(enable(copy))]
|
||||
time_offset: Float,
|
||||
/// Whether clients should not render media stream whose presentation times
|
||||
/// are prior to the specified time offset.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use hls_m3u8::tags::ExtXStart;
|
||||
/// use hls_m3u8::types::Float;
|
||||
///
|
||||
/// let mut start = ExtXStart::new(Float::new(20.123456));
|
||||
/// # assert_eq!(start.is_precise(), false);
|
||||
/// start.set_is_precise(true);
|
||||
///
|
||||
|
@ -37,76 +57,40 @@ impl ExtXStart {
|
|||
|
||||
/// Makes a new [`ExtXStart`] tag.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the `time_offset` is infinite or [`NaN`].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use hls_m3u8::tags::ExtXStart;
|
||||
/// let start = ExtXStart::new(20.123456);
|
||||
/// ```
|
||||
/// use hls_m3u8::types::Float;
|
||||
///
|
||||
/// [`NaN`]: core::f64::NAN
|
||||
pub fn new(time_offset: f32) -> Self {
|
||||
/// let start = ExtXStart::new(Float::new(20.123456));
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub const fn new(time_offset: Float) -> Self {
|
||||
Self {
|
||||
time_offset: Float::new(time_offset),
|
||||
time_offset,
|
||||
is_precise: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Makes a new [`ExtXStart`] tag with the given `precise` flag.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the `time_offset` is infinite or [`NaN`].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use hls_m3u8::tags::ExtXStart;
|
||||
/// let start = ExtXStart::with_precise(20.123456, true);
|
||||
/// use hls_m3u8::types::Float;
|
||||
///
|
||||
/// let start = ExtXStart::with_precise(Float::new(20.123456), true);
|
||||
/// assert_eq!(start.is_precise(), true);
|
||||
/// ```
|
||||
///
|
||||
/// [`NaN`]: core::f64::NAN
|
||||
pub fn with_precise(time_offset: f32, is_precise: bool) -> Self {
|
||||
#[must_use]
|
||||
pub const fn with_precise(time_offset: Float, is_precise: bool) -> Self {
|
||||
Self {
|
||||
time_offset: Float::new(time_offset),
|
||||
time_offset,
|
||||
is_precise,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the time offset of the media segments in the playlist.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use hls_m3u8::tags::ExtXStart;
|
||||
/// let start = ExtXStart::new(20.123456);
|
||||
///
|
||||
/// assert_eq!(start.time_offset(), 20.123456);
|
||||
/// ```
|
||||
pub const fn time_offset(self) -> f32 { self.time_offset.as_f32() }
|
||||
|
||||
/// Sets the time offset of the media segments in the playlist.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use hls_m3u8::tags::ExtXStart;
|
||||
/// let mut start = ExtXStart::new(20.123456);
|
||||
/// # assert_eq!(start.time_offset(), 20.123456);
|
||||
///
|
||||
/// start.set_time_offset(1.0);
|
||||
///
|
||||
/// assert_eq!(start.time_offset(), 1.0);
|
||||
/// ```
|
||||
pub fn set_time_offset(&mut self, value: f32) -> &mut Self {
|
||||
self.time_offset = Float::new(value);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// This tag requires [`ProtocolVersion::V1`].
|
||||
|
@ -165,12 +149,12 @@ mod test {
|
|||
#[test]
|
||||
fn test_display() {
|
||||
assert_eq!(
|
||||
ExtXStart::new(-1.23).to_string(),
|
||||
ExtXStart::new(Float::new(-1.23)).to_string(),
|
||||
"#EXT-X-START:TIME-OFFSET=-1.23".to_string(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
ExtXStart::with_precise(1.23, true).to_string(),
|
||||
ExtXStart::with_precise(Float::new(1.23), true).to_string(),
|
||||
"#EXT-X-START:TIME-OFFSET=1.23,PRECISE=YES".to_string(),
|
||||
);
|
||||
}
|
||||
|
@ -178,12 +162,12 @@ mod test {
|
|||
#[test]
|
||||
fn test_required_version() {
|
||||
assert_eq!(
|
||||
ExtXStart::new(-1.23).required_version(),
|
||||
ExtXStart::new(Float::new(-1.23)).required_version(),
|
||||
ProtocolVersion::V1,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
ExtXStart::with_precise(1.23, true).required_version(),
|
||||
ExtXStart::with_precise(Float::new(1.23), true).required_version(),
|
||||
ProtocolVersion::V1,
|
||||
);
|
||||
}
|
||||
|
@ -191,17 +175,17 @@ mod test {
|
|||
#[test]
|
||||
fn test_parser() {
|
||||
assert_eq!(
|
||||
ExtXStart::new(-1.23),
|
||||
ExtXStart::new(Float::new(-1.23)),
|
||||
"#EXT-X-START:TIME-OFFSET=-1.23".parse().unwrap(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
ExtXStart::with_precise(1.23, true),
|
||||
ExtXStart::with_precise(Float::new(1.23), true),
|
||||
"#EXT-X-START:TIME-OFFSET=1.23,PRECISE=YES".parse().unwrap(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
ExtXStart::with_precise(1.23, true),
|
||||
ExtXStart::with_precise(Float::new(1.23), true),
|
||||
"#EXT-X-START:TIME-OFFSET=1.23,PRECISE=YES,UNKNOWN=TAG"
|
||||
.parse()
|
||||
.unwrap(),
|
||||
|
|
Loading…
Reference in a new issue