Allow unknown tags at the master playlist level

This commit is contained in:
Rafael Caricio 2021-10-14 21:21:03 +02:00
parent c1ff2b3730
commit dc352301a3
Signed by: rafaelcaricio
GPG key ID: 3C86DBCE8E93C947
3 changed files with 53 additions and 5 deletions

View file

@ -276,6 +276,7 @@ pub enum MasterPlaylistTag {
IndependentSegments,
Comment(String),
Uri(String),
Unknown(ExtTag),
}
pub fn master_playlist_tag(input: &[u8]) -> IResult<&[u8], MasterPlaylistTag> {
@ -291,6 +292,8 @@ pub fn master_playlist_tag(input: &[u8]) -> IResult<&[u8], MasterPlaylistTag> {
| map!(start_tag, MasterPlaylistTag::Start)
| map!(tag!("#EXT-X-INDEPENDENT-SEGMENTS"), |_| MasterPlaylistTag::IndependentSegments)
| map!(ext_tag, MasterPlaylistTag::Unknown)
| map!(comment_tag, MasterPlaylistTag::Comment)
| map!(consume_line, MasterPlaylistTag::Uri)
@ -328,6 +331,9 @@ pub fn master_playlist_from_tags(mut tags: Vec<MasterPlaylistTag>) -> MasterPlay
MasterPlaylistTag::IndependentSegments => {
master_playlist.independent_segments = true;
}
MasterPlaylistTag::Unknown(unknown) => {
master_playlist.unknown_tags.push(unknown);
}
_ => (),
}
}

View file

@ -8,6 +8,7 @@ use std::collections::HashMap;
use std::str::FromStr;
use std::fmt;
use std::f32;
use std::fmt::Display;
macro_rules! write_some_attribute_quoted {
($w:expr, $tag:expr, $o:expr) => (
@ -69,6 +70,7 @@ pub struct MasterPlaylist {
pub start: Option<Start>,
pub independent_segments: bool,
pub alternatives: Vec<AlternativeMedia>, // EXT-X-MEDIA tags
pub unknown_tags: Vec<ExtTag>,
}
impl MasterPlaylist {
@ -100,6 +102,9 @@ impl MasterPlaylist {
if self.independent_segments {
writeln!(w, "#EXT-X-INDEPENDENT-SEGMENTS")?;
}
for unknown_tag in &self.unknown_tags {
writeln!(w, "{}", unknown_tag)?;
}
Ok(())
}
@ -528,11 +533,7 @@ impl MediaSegment {
writeln!(w, "#EXT-X-DATERANGE:{}", v)?;
}
for unknown_tag in &self.unknown_tags {
write!(w, "#EXT-{}", unknown_tag.tag)?;
if let Some(v) = &unknown_tag.rest {
writeln!(w, ":{}", v)?;
}
write!(w, "\n")?;
writeln!(w, "{}", unknown_tag)?;
}
write!(w, "#EXTINF:{},", self.duration)?;
@ -692,3 +693,43 @@ pub struct ExtTag {
pub rest: Option<String>,
}
impl Display for ExtTag {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "#EXT-{}", self.tag)?;
if let Some(v) = &self.rest {
write!(f, ":{}", v)?;
}
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn ext_tag_with_value_is_printable() {
let cue_out_tag = ExtTag {
tag: "X-CUE-OUT".into(),
rest: Some("DURATION=30".into()),
};
let mut output = Vec::new();
write!(output, "{}", cue_out_tag);
assert_eq!(std::str::from_utf8(output.as_slice()).unwrap(), "#EXT-X-CUE-OUT:DURATION=30")
}
#[test]
fn ext_tag_without_value_is_printable() {
let cue_in_tag = ExtTag {
tag: "X-CUE-IN".into(),
rest: None,
};
let mut output = Vec::new();
write!(output, "{}", cue_in_tag);
assert_eq!(std::str::from_utf8(output.as_slice()).unwrap(), "#EXT-X-CUE-IN")
}
}

View file

@ -390,6 +390,7 @@ fn create_and_parse_master_playlist_full() {
precise: Some("YES".into()),
}),
independent_segments: true,
unknown_tags: vec![],
});
let playlist_parsed = print_create_and_parse_playlist(&mut playlist_original);
assert_eq!(playlist_original, playlist_parsed);