mirror of
https://github.com/sile/hls_m3u8.git
synced 2024-09-27 22:11:54 +00:00
added cue-in, cue-out, stubbed SCTE-OUT
This commit is contained in:
parent
ac57417cc7
commit
cd5868e705
6 changed files with 135 additions and 6 deletions
|
@ -90,6 +90,8 @@ pub enum Tag {
|
|||
ExtXKey(tags::ExtXKey),
|
||||
ExtXMap(tags::ExtXMap),
|
||||
ExtXProgramDateTime(tags::ExtXProgramDateTime),
|
||||
ExtXCueOut(tags::ExtXCueOut),
|
||||
ExtXCueIn(tags::ExtXCueIn),
|
||||
ExtXDateRange(tags::ExtXDateRange),
|
||||
ExtXTargetDuration(tags::ExtXTargetDuration),
|
||||
ExtXMediaSequence(tags::ExtXMediaSequence),
|
||||
|
@ -117,6 +119,8 @@ impl fmt::Display for Tag {
|
|||
Tag::ExtXKey(ref t) => t.fmt(f),
|
||||
Tag::ExtXMap(ref t) => t.fmt(f),
|
||||
Tag::ExtXProgramDateTime(ref t) => t.fmt(f),
|
||||
Tag::ExtXCueOut(ref t) => t.fmt(f),
|
||||
Tag::ExtXCueIn(ref t) => t.fmt(f),
|
||||
Tag::ExtXDateRange(ref t) => t.fmt(f),
|
||||
Tag::ExtXTargetDuration(ref t) => t.fmt(f),
|
||||
Tag::ExtXMediaSequence(ref t) => t.fmt(f),
|
||||
|
@ -154,6 +158,10 @@ impl FromStr for Tag {
|
|||
track!(s.parse().map(Tag::ExtXMap))
|
||||
} else if s.starts_with(tags::ExtXProgramDateTime::PREFIX) {
|
||||
track!(s.parse().map(Tag::ExtXProgramDateTime))
|
||||
} else if s.starts_with(tags::ExtXCueOut::PREFIX) {
|
||||
track!(s.parse().map(Tag::ExtXCueOut))
|
||||
} else if s.starts_with(tags::ExtXCueIn::PREFIX) {
|
||||
track!(s.parse().map(Tag::ExtXCueIn))
|
||||
} else if s.starts_with(tags::ExtXTargetDuration::PREFIX) {
|
||||
track!(s.parse().map(Tag::ExtXTargetDuration))
|
||||
} else if s.starts_with(tags::ExtXDateRange::PREFIX) {
|
||||
|
|
|
@ -329,6 +329,8 @@ impl FromStr for MasterPlaylist {
|
|||
| Tag::ExtXKey(_)
|
||||
| Tag::ExtXMap(_)
|
||||
| Tag::ExtXProgramDateTime(_)
|
||||
| Tag::ExtXCueOut(_)
|
||||
| Tag::ExtXCueIn(_)
|
||||
| Tag::ExtXDateRange(_)
|
||||
| Tag::ExtXTargetDuration(_)
|
||||
| Tag::ExtXMediaSequence(_)
|
||||
|
|
|
@ -56,7 +56,6 @@ impl MediaPlaylistBuilder {
|
|||
self.version = Some(version);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the given tag to the resulting playlist.
|
||||
pub fn tag<T: Into<MediaPlaylistTag>>(&mut self, tag: T) -> &mut Self {
|
||||
match tag.into() {
|
||||
|
@ -365,6 +364,14 @@ impl MediaPlaylistOptions {
|
|||
has_partial_segment = true;
|
||||
segment.tag(t);
|
||||
}
|
||||
Tag::ExtXCueOut(t) => {
|
||||
has_partial_segment = true;
|
||||
segment.tag(t);
|
||||
}
|
||||
Tag::ExtXCueIn(t) => {
|
||||
has_partial_segment = true;
|
||||
segment.tag(t);
|
||||
}
|
||||
Tag::ExtXDateRange(t) => {
|
||||
has_partial_segment = true;
|
||||
segment.tag(t);
|
||||
|
|
|
@ -2,8 +2,8 @@ use std::fmt;
|
|||
use std::iter;
|
||||
|
||||
use tags::{
|
||||
ExtInf, ExtXByteRange, ExtXDateRange, ExtXDiscontinuity, ExtXKey, ExtXMap, ExtXProgramDateTime,
|
||||
MediaSegmentTag,
|
||||
ExtInf, ExtXByteRange, ExtXCueIn, ExtXCueOut, ExtXDateRange, ExtXDiscontinuity, ExtXKey,
|
||||
ExtXMap, ExtXProgramDateTime, MediaSegmentTag,
|
||||
};
|
||||
use types::{ProtocolVersion, SingleLineString};
|
||||
use {ErrorKind, Result};
|
||||
|
@ -17,6 +17,8 @@ pub struct MediaSegmentBuilder {
|
|||
date_range_tag: Option<ExtXDateRange>,
|
||||
discontinuity_tag: Option<ExtXDiscontinuity>,
|
||||
program_date_time_tag: Option<ExtXProgramDateTime>,
|
||||
cue_out_tag: Option<ExtXCueOut>,
|
||||
cue_in_tag: Option<ExtXCueIn>,
|
||||
inf_tag: Option<ExtInf>,
|
||||
uri: Option<SingleLineString>,
|
||||
}
|
||||
|
@ -30,6 +32,8 @@ impl MediaSegmentBuilder {
|
|||
date_range_tag: None,
|
||||
discontinuity_tag: None,
|
||||
program_date_time_tag: None,
|
||||
cue_out_tag: None,
|
||||
cue_in_tag: None,
|
||||
inf_tag: None,
|
||||
uri: None,
|
||||
}
|
||||
|
@ -51,6 +55,8 @@ impl MediaSegmentBuilder {
|
|||
MediaSegmentTag::ExtXKey(t) => self.key_tags.push(t),
|
||||
MediaSegmentTag::ExtXMap(t) => self.map_tag = Some(t),
|
||||
MediaSegmentTag::ExtXProgramDateTime(t) => self.program_date_time_tag = Some(t),
|
||||
MediaSegmentTag::ExtXCueOut(t) => self.cue_out_tag = Some(t),
|
||||
MediaSegmentTag::ExtXCueIn(t) => self.cue_in_tag = Some(t),
|
||||
}
|
||||
self
|
||||
}
|
||||
|
@ -66,6 +72,8 @@ impl MediaSegmentBuilder {
|
|||
date_range_tag: self.date_range_tag,
|
||||
discontinuity_tag: self.discontinuity_tag,
|
||||
program_date_time_tag: self.program_date_time_tag,
|
||||
cue_out_tag: self.cue_out_tag,
|
||||
cue_in_tag: self.cue_in_tag,
|
||||
inf_tag,
|
||||
uri,
|
||||
})
|
||||
|
@ -86,6 +94,8 @@ pub struct MediaSegment {
|
|||
date_range_tag: Option<ExtXDateRange>,
|
||||
discontinuity_tag: Option<ExtXDiscontinuity>,
|
||||
program_date_time_tag: Option<ExtXProgramDateTime>,
|
||||
cue_out_tag: Option<ExtXCueOut>,
|
||||
cue_in_tag: Option<ExtXCueIn>,
|
||||
inf_tag: ExtInf,
|
||||
uri: SingleLineString,
|
||||
}
|
||||
|
@ -109,6 +119,12 @@ impl fmt::Display for MediaSegment {
|
|||
if let Some(ref t) = self.program_date_time_tag {
|
||||
writeln!(f, "{}", t)?;
|
||||
}
|
||||
if let Some(ref t) = self.cue_out_tag {
|
||||
writeln!(f, "{}", t)?;
|
||||
}
|
||||
if let Some(ref t) = self.cue_in_tag {
|
||||
writeln!(f, "{}", t)?;
|
||||
}
|
||||
writeln!(f, "{}", self.inf_tag)?;
|
||||
writeln!(f, "{}", self.uri)?;
|
||||
Ok(())
|
||||
|
@ -145,6 +161,14 @@ impl MediaSegment {
|
|||
self.program_date_time_tag.as_ref()
|
||||
}
|
||||
|
||||
/// Returns the `EXT-X-CUE-OUT` tag associated with the media segment.
|
||||
pub fn cue_out_tag(&self) -> Option<&ExtXCueOut> {
|
||||
self.cue_out_tag.as_ref()
|
||||
}
|
||||
/// Returns the `EXT-X-CUE-IN` tag associated with the media segment.
|
||||
pub fn cue_in_tag(&self) -> Option<&ExtXCueIn> {
|
||||
self.cue_in_tag.as_ref()
|
||||
}
|
||||
/// Returns the `EXT-X-MAP` tag associated with the media segment.
|
||||
pub fn map_tag(&self) -> Option<&ExtXMap> {
|
||||
self.map_tag.as_ref()
|
||||
|
|
|
@ -339,6 +339,71 @@ impl FromStr for ExtXProgramDateTime {
|
|||
}
|
||||
}
|
||||
|
||||
/// [EXT-X-CUE-OUT]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ExtXCueOut {
|
||||
///seconds in ad pod
|
||||
duration: Duration,
|
||||
}
|
||||
impl ExtXCueOut {
|
||||
pub(crate) const PREFIX: &'static str = "#EXT-X-CUE-OUT:";
|
||||
|
||||
/// Makes a new `ExtXCueOut` tag.
|
||||
pub fn new(duration: Duration) -> Self {
|
||||
let duration = Duration::from_secs(duration.as_secs());
|
||||
ExtXCueOut { duration }
|
||||
}
|
||||
|
||||
/// Returns the date-time of the first sample of the associated media segment.
|
||||
pub fn duration(&self) -> &Duration {
|
||||
&self.duration
|
||||
}
|
||||
|
||||
/// Returns the protocol compatibility version that this tag requires.
|
||||
pub fn requires_version(&self) -> ProtocolVersion {
|
||||
ProtocolVersion::V1
|
||||
}
|
||||
}
|
||||
impl fmt::Display for ExtXCueOut {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}{}", Self::PREFIX, self.duration.as_secs())
|
||||
}
|
||||
}
|
||||
impl FromStr for ExtXCueOut {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
track_assert!(s.starts_with(Self::PREFIX), ErrorKind::InvalidInput);
|
||||
let duration = may_invalid!(s.split_at(Self::PREFIX.len()).1.parse())?;
|
||||
Ok(ExtXCueOut {
|
||||
duration: Duration::from_secs(duration),
|
||||
})
|
||||
}
|
||||
}
|
||||
///CUE-IN
|
||||
///
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ExtXCueIn;
|
||||
impl ExtXCueIn {
|
||||
pub(crate) const PREFIX: &'static str = "#EXT-X-CUE-IN";
|
||||
|
||||
/// Returns the protocol compatibility version that this tag requires.
|
||||
pub fn requires_version(self) -> ProtocolVersion {
|
||||
ProtocolVersion::V1
|
||||
}
|
||||
}
|
||||
impl fmt::Display for ExtXCueIn {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Self::PREFIX.fmt(f)
|
||||
}
|
||||
}
|
||||
impl FromStr for ExtXCueIn {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
track_assert_eq!(s, Self::PREFIX, ErrorKind::InvalidInput);
|
||||
Ok(ExtXCueIn)
|
||||
}
|
||||
}
|
||||
/// [4.3.2.7. EXT-X-DATERANGE]
|
||||
///
|
||||
/// [4.3.2.7. EXT-X-DATERANGE]: https://tools.ietf.org/html/rfc8216#section-4.3.2.7
|
||||
|
@ -439,7 +504,10 @@ impl FromStr for ExtXDateRange {
|
|||
planned_duration = Some(seconds.to_duration());
|
||||
}
|
||||
"SCTE35-CMD" => scte35_cmd = Some(track!(value.parse())?),
|
||||
"SCTE35-OUT" => scte35_out = Some(track!(value.parse())?),
|
||||
"SCTE35-OUT" => {
|
||||
scte35_out = Some(QuotedString::new(value.to_string())?);
|
||||
// scte35_out = Some(track!(value.parse())?),
|
||||
}
|
||||
"SCTE35-IN" => scte35_in = Some(track!(value.parse())?),
|
||||
"END-ON-NEXT" => {
|
||||
track_assert_eq!(value, "YES", ErrorKind::InvalidInput);
|
||||
|
@ -602,7 +670,6 @@ mod test {
|
|||
assert_eq!(tag.to_string(), text);
|
||||
assert_eq!(tag.requires_version(), ProtocolVersion::V6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ext_x_program_date_time() {
|
||||
let text = "#EXT-X-PROGRAM-DATE-TIME:2010-02-19T14:54:23.031+08:00";
|
||||
|
@ -612,4 +679,20 @@ mod test {
|
|||
assert_eq!(tag.to_string(), text);
|
||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
||||
}
|
||||
#[test]
|
||||
fn ext_x_cue_out() {
|
||||
let tag = ExtXCueOut::new(Duration::from_secs(24));
|
||||
let text = "#EXT-X-CUE-OUT:24";
|
||||
assert_eq!(text.parse().ok(), Some(tag));
|
||||
assert_eq!(tag.to_string(), text);
|
||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
||||
}
|
||||
#[test]
|
||||
fn ext_x_cue_in() {
|
||||
let tag = ExtXCueIn::new();
|
||||
let text = "#EXT-X-CUE-OUT";
|
||||
assert_eq!(text.parse().ok(), Some(tag));
|
||||
assert_eq!(tag.to_string(), text);
|
||||
assert_eq!(tag.requires_version(), ProtocolVersion::V1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,8 @@ pub use self::media_playlist::{
|
|||
ExtXTargetDuration,
|
||||
};
|
||||
pub use self::media_segment::{
|
||||
ExtInf, ExtXByteRange, ExtXDateRange, ExtXDiscontinuity, ExtXKey, ExtXMap, ExtXProgramDateTime,
|
||||
ExtInf, ExtXByteRange, ExtXCueIn, ExtXCueOut, ExtXDateRange, ExtXDiscontinuity, ExtXKey,
|
||||
ExtXMap, ExtXProgramDateTime,
|
||||
};
|
||||
|
||||
mod basic;
|
||||
|
@ -107,6 +108,8 @@ pub enum MediaSegmentTag {
|
|||
ExtXKey(ExtXKey),
|
||||
ExtXMap(ExtXMap),
|
||||
ExtXProgramDateTime(ExtXProgramDateTime),
|
||||
ExtXCueOut(ExtXCueOut),
|
||||
ExtXCueIn(ExtXCueIn),
|
||||
}
|
||||
impl_from!(MediaSegmentTag, ExtInf);
|
||||
impl_from!(MediaSegmentTag, ExtXByteRange);
|
||||
|
@ -115,6 +118,8 @@ impl_from!(MediaSegmentTag, ExtXDiscontinuity);
|
|||
impl_from!(MediaSegmentTag, ExtXKey);
|
||||
impl_from!(MediaSegmentTag, ExtXMap);
|
||||
impl_from!(MediaSegmentTag, ExtXProgramDateTime);
|
||||
impl_from!(MediaSegmentTag, ExtXCueOut);
|
||||
impl_from!(MediaSegmentTag, ExtXCueIn);
|
||||
|
||||
fn parse_yes_or_no(s: &str) -> Result<bool> {
|
||||
match s {
|
||||
|
|
Loading…
Reference in a new issue