mirror of
https://github.com/sile/hls_m3u8.git
synced 2024-11-25 00:20:59 +00:00
improve StreamData
This commit is contained in:
parent
0be0c7ddfb
commit
c7419c864f
5 changed files with 142 additions and 34 deletions
|
@ -418,7 +418,7 @@ mod tests {
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(150000)
|
||||
.codecs("avc1.42e00a,mp4a.40.2")
|
||||
.codecs(&["avc1.42e00a", "mp4a.40.2"])
|
||||
.resolution((416, 234))
|
||||
.build()
|
||||
.unwrap()
|
||||
|
@ -431,7 +431,7 @@ mod tests {
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(240000)
|
||||
.codecs("avc1.42e00a,mp4a.40.2")
|
||||
.codecs(&["avc1.42e00a", "mp4a.40.2"])
|
||||
.resolution((416, 234))
|
||||
.build()
|
||||
.unwrap()
|
||||
|
@ -444,7 +444,7 @@ mod tests {
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(440000)
|
||||
.codecs("avc1.42e00a,mp4a.40.2")
|
||||
.codecs(&["avc1.42e00a", "mp4a.40.2"])
|
||||
.resolution((416, 234))
|
||||
.build()
|
||||
.unwrap()
|
||||
|
@ -457,7 +457,7 @@ mod tests {
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(640000)
|
||||
.codecs("avc1.42e00a,mp4a.40.2")
|
||||
.codecs(&["avc1.42e00a", "mp4a.40.2"])
|
||||
.resolution((640, 360))
|
||||
.build()
|
||||
.unwrap()
|
||||
|
@ -470,7 +470,7 @@ mod tests {
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(64000)
|
||||
.codecs("mp4a.40.5")
|
||||
.codecs(&["mp4a.40.5"])
|
||||
.build()
|
||||
.unwrap()
|
||||
},
|
||||
|
@ -493,7 +493,7 @@ mod tests {
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(150000)
|
||||
.codecs("avc1.42e00a,mp4a.40.2")
|
||||
.codecs(&["avc1.42e00a", "mp4a.40.2"])
|
||||
.resolution((416, 234))
|
||||
.build()
|
||||
.unwrap()
|
||||
|
@ -506,7 +506,7 @@ mod tests {
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(240000)
|
||||
.codecs("avc1.42e00a,mp4a.40.2")
|
||||
.codecs(&["avc1.42e00a", "mp4a.40.2"])
|
||||
.resolution((416, 234))
|
||||
.build()
|
||||
.unwrap()
|
||||
|
@ -519,7 +519,7 @@ mod tests {
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(440000)
|
||||
.codecs("avc1.42e00a,mp4a.40.2")
|
||||
.codecs(&["avc1.42e00a", "mp4a.40.2"])
|
||||
.resolution((416, 234))
|
||||
.build()
|
||||
.unwrap()
|
||||
|
@ -532,7 +532,7 @@ mod tests {
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(640000)
|
||||
.codecs("avc1.42e00a,mp4a.40.2")
|
||||
.codecs(&["avc1.42e00a", "mp4a.40.2"])
|
||||
.resolution((640, 360))
|
||||
.build()
|
||||
.unwrap()
|
||||
|
@ -545,7 +545,7 @@ mod tests {
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(64000)
|
||||
.codecs("mp4a.40.5")
|
||||
.codecs(&["mp4a.40.5"])
|
||||
.build()
|
||||
.unwrap()
|
||||
},
|
||||
|
|
99
src/types/codecs.rs
Normal file
99
src/types/codecs.rs
Normal file
|
@ -0,0 +1,99 @@
|
|||
use core::fmt;
|
||||
use core::str::FromStr;
|
||||
|
||||
use derive_more::{AsMut, AsRef, Deref, DerefMut};
|
||||
|
||||
use crate::Error;
|
||||
|
||||
/// A list of formats, where each format specifies a media sample type that is
|
||||
/// present in one or more renditions specified by the [`VariantStream`].
|
||||
///
|
||||
/// Valid format identifiers are those in the ISO Base Media File Format Name
|
||||
/// Space defined by "The 'Codecs' and 'Profiles' Parameters for "Bucket" Media
|
||||
/// Types" ([RFC6381]).
|
||||
///
|
||||
/// For example, a stream containing AAC low complexity (AAC-LC) audio and H.264
|
||||
/// Main Profile Level 3.0 video would be
|
||||
///
|
||||
/// ```
|
||||
/// # use hls_m3u8::types::Codecs;
|
||||
/// let codecs = Codecs::from(&["mp4a.40.2", "avc1.4d401e"]);
|
||||
/// ```
|
||||
///
|
||||
/// [RFC6381]: https://tools.ietf.org/html/rfc6381
|
||||
/// [`VariantStream`]: crate::tags::VariantStream
|
||||
#[derive(AsMut, AsRef, Deref, DerefMut, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Codecs {
|
||||
list: Vec<String>,
|
||||
}
|
||||
|
||||
impl Codecs {
|
||||
/// Makes a new (empty) [`Codecs`] struct.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use hls_m3u8::types::Codecs;
|
||||
/// let codecs = Codecs::new();
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn new() -> Self { Self { list: Vec::new() } }
|
||||
}
|
||||
|
||||
impl fmt::Display for Codecs {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if let Some(codec) = self.list.iter().next() {
|
||||
write!(f, "{}", codec)?;
|
||||
|
||||
for codec in self.list.iter().skip(1) {
|
||||
write!(f, ",{}", codec)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl FromStr for Codecs {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||
Ok(Self {
|
||||
list: input.split(',').map(|s| s.into()).collect(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>, I: IntoIterator<Item = T>> From<I> for Codecs {
|
||||
fn from(value: I) -> Self {
|
||||
Self {
|
||||
list: value.into_iter().map(|s| s.as_ref().to_string()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_from() {
|
||||
assert_eq!(Codecs::from(Vec::<&str>::new()), Codecs::new());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_display() {
|
||||
assert_eq!(
|
||||
Codecs::from(vec!["mp4a.40.2", "avc1.4d401e"]).to_string(),
|
||||
"mp4a.40.2,avc1.4d401e".to_string()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parser() {
|
||||
assert_eq!(
|
||||
Codecs::from_str("mp4a.40.2,avc1.4d401e").unwrap(),
|
||||
Codecs::from(vec!["mp4a.40.2", "avc1.4d401e"])
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
mod byte_range;
|
||||
mod channels;
|
||||
mod closed_captions;
|
||||
mod codecs;
|
||||
mod encryption_method;
|
||||
mod hdcp_level;
|
||||
mod in_stream_id;
|
||||
|
@ -19,6 +20,7 @@ mod ufloat;
|
|||
pub use byte_range::*;
|
||||
pub use channels::*;
|
||||
pub use closed_captions::*;
|
||||
pub use codecs::*;
|
||||
pub use encryption_method::*;
|
||||
pub use hdcp_level::*;
|
||||
pub use in_stream_id::*;
|
||||
|
|
|
@ -5,7 +5,7 @@ use derive_builder::Builder;
|
|||
use shorthand::ShortHand;
|
||||
|
||||
use crate::attribute::AttributePairs;
|
||||
use crate::types::{HdcpLevel, ProtocolVersion, Resolution};
|
||||
use crate::types::{Codecs, HdcpLevel, ProtocolVersion, Resolution};
|
||||
use crate::utils::{quote, unquote};
|
||||
use crate::{Error, RequiredVersion};
|
||||
|
||||
|
@ -93,27 +93,34 @@ pub struct StreamData {
|
|||
#[builder(default)]
|
||||
#[shorthand(enable(copy), disable(into, option_as_ref))]
|
||||
average_bandwidth: Option<u64>,
|
||||
/// A string that represents a list of formats, where each format specifies
|
||||
/// a media sample type that is present in one or more renditions specified
|
||||
/// by the [`VariantStream`].
|
||||
/// A list of formats, where each format specifies a media sample type that
|
||||
/// is present in one or more renditions specified by the [`VariantStream`].
|
||||
///
|
||||
/// Valid format identifiers are those in the ISO Base Media File Format
|
||||
/// Name Space defined by "The 'Codecs' and 'Profiles' Parameters for
|
||||
/// "Bucket" Media Types" [RFC6381].
|
||||
/// "Bucket" Media Types" ([RFC6381]).
|
||||
///
|
||||
/// For example, a stream containing AAC low complexity (AAC-LC) audio and
|
||||
/// H.264 Main Profile Level 3.0 video would have a codecs value of
|
||||
/// "mp4a.40.2,avc1.4d401e".
|
||||
/// H.264 Main Profile Level 3.0 video would be
|
||||
///
|
||||
/// ```
|
||||
/// # use hls_m3u8::types::Codecs;
|
||||
/// let codecs = Codecs::from(&["mp4a.40.2", "avc1.4d401e"]);
|
||||
/// ```
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use hls_m3u8::types::StreamData;
|
||||
/// #
|
||||
/// use hls_m3u8::types::Codecs;
|
||||
///
|
||||
/// let mut stream = StreamData::new(20);
|
||||
///
|
||||
/// stream.set_codecs(Some("mp4a.40.2,avc1.4d401e"));
|
||||
/// assert_eq!(stream.codecs(), Some(&"mp4a.40.2,avc1.4d401e".to_string()));
|
||||
/// stream.set_codecs(Some(&["mp4a.40.2", "avc1.4d401e"]));
|
||||
/// assert_eq!(
|
||||
/// stream.codecs(),
|
||||
/// Some(&Codecs::from(&["mp4a.40.2", "avc1.4d401e"]))
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// # Note
|
||||
|
@ -126,7 +133,7 @@ pub struct StreamData {
|
|||
/// crate::tags::VariantStream::ExtXStreamInf
|
||||
/// [RFC6381]: https://tools.ietf.org/html/rfc6381
|
||||
#[builder(default, setter(into))]
|
||||
codecs: Option<String>,
|
||||
codecs: Option<Codecs>,
|
||||
/// The resolution of the stream.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -237,7 +244,7 @@ impl StreamData {
|
|||
/// StreamData::builder()
|
||||
/// .bandwidth(200)
|
||||
/// .average_bandwidth(15)
|
||||
/// .codecs("mp4a.40.2,avc1.4d401e")
|
||||
/// .codecs(&["mp4a.40.2", "avc1.4d401e"])
|
||||
/// .resolution((1920, 1080))
|
||||
/// .hdcp_level(HdcpLevel::Type0)
|
||||
/// .video("video_01")
|
||||
|
@ -297,7 +304,7 @@ impl FromStr for StreamData {
|
|||
.map_err(|e| Error::parse_int(value, e))?,
|
||||
)
|
||||
}
|
||||
"CODECS" => codecs = Some(unquote(value)),
|
||||
"CODECS" => codecs = Some(unquote(value).parse()?),
|
||||
"RESOLUTION" => resolution = Some(value.parse()?),
|
||||
"HDCP-LEVEL" => {
|
||||
hdcp_level = Some(value.parse::<HdcpLevel>().map_err(Error::strum)?)
|
||||
|
@ -346,7 +353,7 @@ mod tests {
|
|||
fn test_display() {
|
||||
let mut stream_data = StreamData::new(200);
|
||||
stream_data.set_average_bandwidth(Some(15));
|
||||
stream_data.set_codecs(Some("mp4a.40.2,avc1.4d401e"));
|
||||
stream_data.set_codecs(Some(&["mp4a.40.2", "avc1.4d401e"]));
|
||||
stream_data.set_resolution(Some((1920, 1080)));
|
||||
stream_data.set_hdcp_level(Some(HdcpLevel::Type0));
|
||||
stream_data.set_video(Some("video"));
|
||||
|
@ -369,7 +376,7 @@ mod tests {
|
|||
fn test_parser() {
|
||||
let mut stream_data = StreamData::new(200);
|
||||
stream_data.set_average_bandwidth(Some(15));
|
||||
stream_data.set_codecs(Some("mp4a.40.2,avc1.4d401e"));
|
||||
stream_data.set_codecs(Some(&["mp4a.40.2", "avc1.4d401e"]));
|
||||
stream_data.set_resolution(Some((1920, 1080)));
|
||||
stream_data.set_hdcp_level(Some(HdcpLevel::Type0));
|
||||
stream_data.set_video(Some("video"));
|
||||
|
|
|
@ -214,7 +214,7 @@ generate_tests! [
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(65000)
|
||||
.codecs("mp4a.40.5")
|
||||
.codecs(&["mp4a.40.5"])
|
||||
.build()
|
||||
.unwrap()
|
||||
},
|
||||
|
@ -280,7 +280,7 @@ generate_tests! [
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(65000)
|
||||
.codecs("mp4a.40.5")
|
||||
.codecs(&["mp4a.40.5"])
|
||||
.build()
|
||||
.unwrap()
|
||||
},
|
||||
|
@ -345,7 +345,7 @@ generate_tests! [
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(1280000)
|
||||
.codecs("...")
|
||||
.codecs(&["..."])
|
||||
.build()
|
||||
.unwrap()
|
||||
},
|
||||
|
@ -357,7 +357,7 @@ generate_tests! [
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(2560000)
|
||||
.codecs("...")
|
||||
.codecs(&["..."])
|
||||
.build()
|
||||
.unwrap()
|
||||
},
|
||||
|
@ -369,7 +369,7 @@ generate_tests! [
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(7680000)
|
||||
.codecs("...")
|
||||
.codecs(&["..."])
|
||||
.build()
|
||||
.unwrap()
|
||||
},
|
||||
|
@ -381,7 +381,7 @@ generate_tests! [
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(65000)
|
||||
.codecs("mp4a.40.5")
|
||||
.codecs(&["mp4a.40.5"])
|
||||
.build()
|
||||
.unwrap()
|
||||
},
|
||||
|
@ -518,7 +518,7 @@ generate_tests! [
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(1280000)
|
||||
.codecs("...")
|
||||
.codecs(&["..."])
|
||||
.video("low")
|
||||
.build()
|
||||
.unwrap()
|
||||
|
@ -531,7 +531,7 @@ generate_tests! [
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(2560000)
|
||||
.codecs("...")
|
||||
.codecs(&["..."])
|
||||
.video("mid")
|
||||
.build()
|
||||
.unwrap()
|
||||
|
@ -544,7 +544,7 @@ generate_tests! [
|
|||
closed_captions: None,
|
||||
stream_data: StreamData::builder()
|
||||
.bandwidth(7680000)
|
||||
.codecs("...")
|
||||
.codecs(&["..."])
|
||||
.video("hi")
|
||||
.build()
|
||||
.unwrap()
|
||||
|
|
Loading…
Reference in a new issue