1
0
Fork 0
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:
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
///
/// ```
/// # 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>>(())
/// ```

View file

@ -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]

View file

@ -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(),