mp4: More robust parsing and updated mapping of rtng atom

This commit is contained in:
Uwe Klotz 2023-01-14 21:42:50 +01:00 committed by Alex
parent 100b7e21b1
commit 06b3b6dbaf
2 changed files with 30 additions and 21 deletions

View file

@ -216,14 +216,22 @@ pub enum AtomData {
}
/// The parental advisory rating
///
/// See also:
/// <https://docs.mp3tag.de/mapping/#itunesadvisory>
/// <https://exiftool.org/TagNames/QuickTime.html>
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AdvisoryRating {
/// A rating of 0
/// *Inoffensive*/*None* (0)
Inoffensive,
/// A rating of 2
Clean,
/// A rating of (1 || > 2)
/// *Explicit* (1 or 4)
///
/// In the past Apple used the value 4 for explicit content
/// that has later been replaced by 1. Both values are considered
/// as valid when reading but only the newer value 1 is written.
Explicit,
/// *Clean*/*Edited* (2)
Clean,
}
impl AdvisoryRating {
@ -231,18 +239,21 @@ impl AdvisoryRating {
pub fn as_u8(&self) -> u8 {
match self {
AdvisoryRating::Inoffensive => 0,
AdvisoryRating::Explicit => 1,
AdvisoryRating::Clean => 2,
AdvisoryRating::Explicit => 4,
}
}
}
impl From<u8> for AdvisoryRating {
fn from(input: u8) -> Self {
impl TryFrom<u8> for AdvisoryRating {
type Error = u8;
fn try_from(input: u8) -> Result<Self, Self::Error> {
match input {
0 => Self::Inoffensive,
2 => Self::Clean,
_ => Self::Explicit,
0 => Ok(Self::Inoffensive),
1 | 4 => Ok(Self::Explicit),
2 => Ok(Self::Clean),
value => Err(value),
}
}
}

View file

@ -152,17 +152,15 @@ impl Ilst {
/// Returns the parental advisory rating according to the `rtng` atom
pub fn advisory_rating(&self) -> Option<AdvisoryRating> {
if let Some(atom) = self.atom(&ADVISORY_RATING) {
let rating = match atom.data().next() {
Some(AtomData::SignedInteger(si)) => *si as u8,
Some(AtomData::Unknown { data: c, .. }) if !c.is_empty() => c[0],
_ => return None,
};
return Some(AdvisoryRating::from(rating));
}
None
self.atom(&ADVISORY_RATING)
.into_iter()
.flat_map(Atom::data)
.filter_map(|data| match data {
AtomData::SignedInteger(si) => u8::try_from(*si).ok(),
AtomData::Unknown { data, .. } => data.first().copied(),
_ => None,
})
.find_map(|rating| AdvisoryRating::try_from(rating).ok())
}
/// Sets the advisory rating