1
0
Fork 0
mirror of https://github.com/sile/hls_m3u8.git synced 2024-06-09 16:59:34 +00:00

improvments to ExtXStart

This commit is contained in:
Luro02 2020-02-24 16:44:02 +01:00
parent 9273e6c16c
commit 6ef8182f2c
No known key found for this signature in database
GPG key ID: B66FD4F74501A9CF
3 changed files with 118 additions and 149 deletions

View file

@ -103,11 +103,12 @@ impl MasterPlaylist {
/// # Example /// # Example
/// ///
/// ``` /// ```
/// # use hls_m3u8::MasterPlaylist;
/// use hls_m3u8::tags::ExtXStart; /// use hls_m3u8::tags::ExtXStart;
/// use hls_m3u8::MasterPlaylist; /// use hls_m3u8::types::Float;
/// ///
/// MasterPlaylist::builder() /// MasterPlaylist::builder()
/// .start(ExtXStart::new(20.123456)) /// .start(ExtXStart::new(Float::new(20.3)))
/// .build()?; /// .build()?;
/// # Ok::<(), Box<dyn ::std::error::Error>>(()) /// # Ok::<(), Box<dyn ::std::error::Error>>(())
/// ``` /// ```

View file

@ -326,53 +326,70 @@ impl fmt::Display for ExtXDateRange {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use crate::types::Float;
use chrono::offset::TimeZone; use chrono::offset::TimeZone;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
const HOURS_IN_SECS: i32 = 3600; // 1 hour = 3600 seconds const HOURS_IN_SECS: i32 = 3600; // 1 hour = 3600 seconds
#[test] macro_rules! generate_tests {
fn test_parser() { ( $( { $left:expr, $right:expr } ),* $(,)* ) => {
assert_eq!( #[test]
"#EXT-X-DATERANGE:\ fn test_display() {
ID=\"splice-6FFFFFF0\",\ $(
START-DATE=\"2014-03-05T11:15:00Z\",\ assert_eq!($left.to_string(), $right.to_string());
PLANNED-DURATION=59.993,\ )*
SCTE35-OUT=0xFC002F0000000000FF000014056F\ }
FFFFF000E011622DCAFF000052636200000000000\
A0008029896F50000008700000000" #[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>() .parse::<ExtXDateRange>()
.unwrap(), .is_err());
}
}
}
generate_tests! {
{
ExtXDateRange::builder() ExtXDateRange::builder()
.id("splice-6FFFFFF0") .id("splice-6FFFFFF0")
.start_date(FixedOffset::east(0).ymd(2014, 3, 5).and_hms(11, 15, 0)) .start_date(FixedOffset::east(0).ymd(2014, 3, 5).and_hms(11, 15, 0))
.planned_duration(Duration::from_secs_f64(59.993)) .planned_duration(Duration::from_secs_f64(59.993))
.scte35_out( .scte35_out(concat!(
"0xFC002F0000000000FF00001\ "0xFC002F0000000000FF00001",
4056FFFFFF000E011622DCAFF0\ "4056FFFFFF000E011622DCAFF0",
00052636200000000000A00080\ "00052636200000000000A00080",
29896F50000008700000000" "29896F50000008700000000"
) ))
.build() .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(), .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() ExtXDateRange::builder()
.id("test_id") .id("test_id")
.class("test_class") .class("test_class")
@ -380,61 +397,28 @@ mod test {
.end_date(FixedOffset::east(0).ymd(2014, 3, 5).and_hms(11, 16, 0)) .end_date(FixedOffset::east(0).ymd(2014, 3, 5).and_hms(11, 16, 0))
.duration(Duration::from_secs_f64(60.1)) .duration(Duration::from_secs_f64(60.1))
.planned_duration(Duration::from_secs_f64(59.993)) .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_cmd("0xFC002F0000000000FF2")
.scte35_out("0xFC002F0000000000FF0") .scte35_out("0xFC002F0000000000FF0")
.scte35_in("0xFC002F0000000000FF1") .scte35_in("0xFC002F0000000000FF1")
.end_on_next(true) .end_on_next(true)
.build() .build()
.unwrap() .unwrap(),
); concat!(
"#EXT-X-DATERANGE:",
assert!("#EXT-X-DATERANGE:END-ON-NEXT=NO" "ID=\"test_id\",",
.parse::<ExtXDateRange>() "CLASS=\"test_class\",",
.is_err()); "START-DATE=\"2014-03-05T11:15:00Z\",",
"END-DATE=\"2014-03-05T11:16:00Z\",",
assert!("garbage".parse::<ExtXDateRange>().is_err()); "DURATION=60.1,",
assert!("".parse::<ExtXDateRange>().is_err()); "PLANNED-DURATION=59.993,",
"SCTE35-CMD=0xFC002F0000000000FF2,",
assert!("#EXT-X-DATERANGE:\ "SCTE35-OUT=0xFC002F0000000000FF0,",
ID=\"test_id\",\ "SCTE35-IN=0xFC002F0000000000FF1,",
START-DATE=\"2014-03-05T11:15:00Z\",\ "X-CUSTOM=45.3,",
END-ON-NEXT=YES" "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"
)
} }
#[test] #[test]

View file

@ -8,22 +8,42 @@ use crate::types::{Float, ProtocolVersion};
use crate::utils::{parse_yes_or_no, tag}; use crate::utils::{parse_yes_or_no, tag};
use crate::{Error, RequiredVersion}; 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)] #[derive(ShortHand, PartialOrd, Debug, Clone, Copy, PartialEq)]
#[shorthand(enable(must_use))] #[shorthand(enable(must_use))]
pub struct ExtXStart { pub struct ExtXStart {
#[shorthand(enable(skip))] /// The time offset of the [`MediaSegment`]s in the playlist.
time_offset: Float,
/// Returns whether clients should not render media stream whose
/// presentation times are prior to the specified time offset.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// # use hls_m3u8::tags::ExtXStart; /// # 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); /// # assert_eq!(start.is_precise(), false);
/// start.set_is_precise(true); /// start.set_is_precise(true);
/// ///
@ -37,76 +57,40 @@ impl ExtXStart {
/// Makes a new [`ExtXStart`] tag. /// Makes a new [`ExtXStart`] tag.
/// ///
/// # Panics
///
/// Panics if the `time_offset` is infinite or [`NaN`].
///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// # use hls_m3u8::tags::ExtXStart; /// # use hls_m3u8::tags::ExtXStart;
/// let start = ExtXStart::new(20.123456); /// use hls_m3u8::types::Float;
/// ```
/// ///
/// [`NaN`]: core::f64::NAN /// let start = ExtXStart::new(Float::new(20.123456));
pub fn new(time_offset: f32) -> Self { /// ```
#[must_use]
pub const fn new(time_offset: Float) -> Self {
Self { Self {
time_offset: Float::new(time_offset), time_offset,
is_precise: false, is_precise: false,
} }
} }
/// Makes a new [`ExtXStart`] tag with the given `precise` flag. /// Makes a new [`ExtXStart`] tag with the given `precise` flag.
/// ///
/// # Panics
///
/// Panics if the `time_offset` is infinite or [`NaN`].
///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// # use hls_m3u8::tags::ExtXStart; /// # 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); /// assert_eq!(start.is_precise(), true);
/// ``` /// ```
/// #[must_use]
/// [`NaN`]: core::f64::NAN pub const fn with_precise(time_offset: Float, is_precise: bool) -> Self {
pub fn with_precise(time_offset: f32, is_precise: bool) -> Self {
Self { Self {
time_offset: Float::new(time_offset), time_offset,
is_precise, 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`]. /// This tag requires [`ProtocolVersion::V1`].
@ -165,12 +149,12 @@ mod test {
#[test] #[test]
fn test_display() { fn test_display() {
assert_eq!( 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(), "#EXT-X-START:TIME-OFFSET=-1.23".to_string(),
); );
assert_eq!( 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(), "#EXT-X-START:TIME-OFFSET=1.23,PRECISE=YES".to_string(),
); );
} }
@ -178,12 +162,12 @@ mod test {
#[test] #[test]
fn test_required_version() { fn test_required_version() {
assert_eq!( assert_eq!(
ExtXStart::new(-1.23).required_version(), ExtXStart::new(Float::new(-1.23)).required_version(),
ProtocolVersion::V1, ProtocolVersion::V1,
); );
assert_eq!( assert_eq!(
ExtXStart::with_precise(1.23, true).required_version(), ExtXStart::with_precise(Float::new(1.23), true).required_version(),
ProtocolVersion::V1, ProtocolVersion::V1,
); );
} }
@ -191,17 +175,17 @@ mod test {
#[test] #[test]
fn test_parser() { fn test_parser() {
assert_eq!( assert_eq!(
ExtXStart::new(-1.23), ExtXStart::new(Float::new(-1.23)),
"#EXT-X-START:TIME-OFFSET=-1.23".parse().unwrap(), "#EXT-X-START:TIME-OFFSET=-1.23".parse().unwrap(),
); );
assert_eq!( 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(), "#EXT-X-START:TIME-OFFSET=1.23,PRECISE=YES".parse().unwrap(),
); );
assert_eq!( 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" "#EXT-X-START:TIME-OFFSET=1.23,PRECISE=YES,UNKNOWN=TAG"
.parse() .parse()
.unwrap(), .unwrap(),