MP4: Create DataType enum, replacing constants

This commit is contained in:
Serial 2024-09-14 16:15:06 -04:00 committed by Alex
parent 637052978b
commit 9eb35ae1b9
6 changed files with 336 additions and 95 deletions

View file

@ -1,5 +1,6 @@
use crate::error::Result;
use crate::macros::err;
use crate::mp4::ilst::data_type::DataType;
use crate::mp4::AtomIdent;
use crate::picture::Picture;
@ -213,7 +214,10 @@ impl<'a> Atom<'a> {
pub(crate) fn unknown_implicit(ident: AtomIdent<'_>, data: Vec<u8>) -> Self {
Self {
ident: ident.into_owned(),
data: AtomDataStorage::Single(AtomData::Unknown { code: 0, data }),
data: AtomDataStorage::Single(AtomData::Unknown {
code: DataType::Reserved,
data,
}),
}
}
@ -247,8 +251,7 @@ impl Debug for Atom<'_> {
/// NOTES:
///
/// * This only covers the most common data types.
/// See the list of [well-known data types](https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW34)
/// for codes.
/// See the list of [DataType] for all known types.
/// * There are only two variants for integers, which
/// will come from codes `21` and `22`. All other integer
/// types will be stored as [`AtomData::Unknown`], refer
@ -290,51 +293,52 @@ pub enum AtomData {
/// variant.
Unknown {
/// The code, or type of the item
code: u32,
code: DataType,
/// The binary data of the atom
data: Vec<u8>,
},
}
/// The parental advisory rating
impl AtomData {
/// Get the [`DataType`] of the atom
///
/// See also:
/// <https://docs.mp3tag.de/mapping/#itunesadvisory>
/// <https://exiftool.org/TagNames/QuickTime.html>
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AdvisoryRating {
/// *Inoffensive*/*None* (0)
Inoffensive,
/// *Explicit* (1 or 4)
/// Note that for [`AtomData::Picture`], the type is determined by the picture's MIME type.
/// If the MIME type is unknown (or unset), the data type will be [`DataType::Reserved`].
///
/// 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 {
/// Returns the rating as it appears in the `rtng` atom
pub fn as_u8(&self) -> u8 {
/// # Examples
///
/// ```rust
/// use lofty::mp4::{AtomData, DataType};
/// use lofty::picture::{MimeType, Picture, PictureType};
///
/// let data = AtomData::UTF8(String::from("foo"));
/// assert_eq!(data.data_type(), DataType::Utf8);
///
/// let data = AtomData::SignedInteger(42);
/// assert_eq!(data.data_type(), DataType::BeSignedInteger);
///
/// let data = AtomData::Picture(Picture::new_unchecked(
/// PictureType::CoverFront,
/// Some(MimeType::Jpeg),
/// None,
/// Vec::new(),
/// ));
/// assert_eq!(data.data_type(), DataType::Jpeg);
/// ```
pub fn data_type(&self) -> DataType {
match self {
AdvisoryRating::Inoffensive => 0,
AdvisoryRating::Explicit => 1,
AdvisoryRating::Clean => 2,
}
}
}
AtomData::UTF8(_) => DataType::Utf8,
AtomData::UTF16(_) => DataType::Utf16,
AtomData::SignedInteger(_) | AtomData::Bool(_) => DataType::BeSignedInteger,
AtomData::UnsignedInteger(_) => DataType::BeUnsignedInteger,
AtomData::Picture(p) => {
let Some(mime) = p.mime_type() else {
return DataType::Reserved;
};
impl TryFrom<u8> for AdvisoryRating {
type Error = u8;
fn try_from(input: u8) -> std::result::Result<Self, Self::Error> {
match input {
0 => Ok(Self::Inoffensive),
1 | 4 => Ok(Self::Explicit),
2 => Ok(Self::Clean),
value => Err(value),
DataType::from(mime)
},
AtomData::Unknown { code, .. } => *code,
}
}
}

View file

@ -0,0 +1,200 @@
use crate::picture::MimeType;
/// The [well known] basic data types
///
/// This should cover all the data types you'll encounter in an MP4 file.
///
/// [well known]: https://developer.apple.com/documentation/quicktime-file-format/well-known_types
// OLD LINKS:
// * https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW35
#[repr(u32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum DataType {
/// Reserved for use where no type needs to be indicated
Reserved = 0,
/// UTF-8 string without any count or NULL terminator
Utf8 = 1,
/// A big-endian UTF-16 string
Utf16 = 2,
/// Deprecated unless it is needed for special Japanese characters
SJis = 3,
/// The UTF-8 variant storage of a string for sorting only
Utf8Sort = 4,
/// The UTF-16 variant storage of a string for sorting only
Utf16Sort = 5,
/// **DEPRECATED** A GIF image
Gif = 12,
/// A JPEG in a JFIF wrapper
Jpeg = 13,
/// A PNG in a PNG wrapper
Png = 14,
/// A big-endian signed integer in 1,2,3 or 4 bytes
BeSignedInteger = 21,
/// A big-endian unsigned integer in 1,2,3 or 4 bytes; size of value determines integer size
BeUnsignedInteger = 22,
/// A big-endian 32-bit floating point value (IEEE754)
BeFloat32 = 23,
/// A big-endian 64-bit floating point value (IEEE754)
BeFloat64 = 24,
/// Windows bitmap format graphics
Bmp = 27,
/// A QuickTime metadata atom
QuicktimeMetadata = 28,
/// An 8-bit signed integer
Signed8BitInteger = 65,
/// A big-endian 16-bit signed integer
Be16BitSignedInteger = 66,
/// A big-endian 32-bit signed integer
Be32BitSignedInteger = 67,
/// A block of data representing a two dimensional (2D) point with 32-bit big-endian floating point x and y coordinates. It has the structure:
///
/// ```c
/// struct {
/// BEFloat32 x;
/// BEFloat32 y;
/// }
/// ```
BePointF32 = 70,
/// A block of data representing 2D dimensions with 32-bit big-endian floating point width and height. It has the structure:
///
/// ```c
/// struct {
/// BEFloat32 width;
/// BEFloat32 height;
/// }
/// ```
BeDimensionsF32 = 71,
/// A block of data representing a 2D rectangle with 32-bit big-endian floating point x and y coordinates and a 32-bit big-endian floating point width and height size. It has the structure:
///
/// ```c
/// struct {
/// BEFloat32 x;
/// BEFloat32 y;
/// BEFloat32 width;
/// BEFloat32 height;
/// }
/// ```
///
/// or the equivalent structure:
///
/// ```c
/// struct {
/// PointF32 origin;
/// DimensionsF32 size;
/// }
/// ```
BeRectF32 = 72,
/// A big-endian 64-bit signed integer
Be64BitSignedInteger = 74,
/// An 8-bit unsigned integer
Unsigned8BitInteger = 75,
/// A big-endian 16-bit unsigned integer
Be16BitUnsignedInteger = 76,
/// A big-endian 32-bit unsigned integer
Be32BitUnsignedInteger = 77,
/// A big-endian 64-bit unsigned integer
Be64BitUnsignedInteger = 78,
/// A block of data representing a 3x3 transformation matrix. It has the structure:
///
/// ```c
/// struct {
/// BEFloat64 matrix[3][3];
/// }
/// ```
AffineTransformF64 = 79,
/// Some other data type
Other(u32),
}
impl From<u32> for DataType {
fn from(value: u32) -> Self {
match value {
0 => DataType::Reserved,
1 => DataType::Utf8,
2 => DataType::Utf16,
3 => DataType::SJis,
4 => DataType::Utf8Sort,
5 => DataType::Utf16Sort,
12 => DataType::Gif,
13 => DataType::Jpeg,
14 => DataType::Png,
21 => DataType::BeSignedInteger,
22 => DataType::BeUnsignedInteger,
23 => DataType::BeFloat32,
24 => DataType::BeFloat64,
27 => DataType::Bmp,
28 => DataType::QuicktimeMetadata,
65 => DataType::Signed8BitInteger,
66 => DataType::Be16BitSignedInteger,
67 => DataType::Be32BitSignedInteger,
70 => DataType::BePointF32,
71 => DataType::BeDimensionsF32,
72 => DataType::BeRectF32,
74 => DataType::Be64BitSignedInteger,
75 => DataType::Unsigned8BitInteger,
76 => DataType::Be16BitUnsignedInteger,
77 => DataType::Be32BitUnsignedInteger,
78 => DataType::Be64BitUnsignedInteger,
79 => DataType::AffineTransformF64,
other => DataType::Other(other),
}
}
}
impl From<DataType> for u32 {
fn from(value: DataType) -> Self {
match value {
DataType::Reserved => 0,
DataType::Utf8 => 1,
DataType::Utf16 => 2,
DataType::SJis => 3,
DataType::Utf8Sort => 4,
DataType::Utf16Sort => 5,
DataType::Gif => 12,
DataType::Jpeg => 13,
DataType::Png => 14,
DataType::BeSignedInteger => 21,
DataType::BeUnsignedInteger => 22,
DataType::BeFloat32 => 23,
DataType::BeFloat64 => 24,
DataType::Bmp => 27,
DataType::QuicktimeMetadata => 28,
DataType::Signed8BitInteger => 65,
DataType::Be16BitSignedInteger => 66,
DataType::Be32BitSignedInteger => 67,
DataType::BePointF32 => 70,
DataType::BeDimensionsF32 => 71,
DataType::BeRectF32 => 72,
DataType::Be64BitSignedInteger => 74,
DataType::Unsigned8BitInteger => 75,
DataType::Be16BitUnsignedInteger => 76,
DataType::Be32BitUnsignedInteger => 77,
DataType::Be64BitUnsignedInteger => 78,
DataType::AffineTransformF64 => 79,
DataType::Other(other) => other,
}
}
}
impl From<MimeType> for DataType {
fn from(value: MimeType) -> Self {
DataType::from(&value)
}
}
impl From<&MimeType> for DataType {
fn from(value: &MimeType) -> Self {
match value {
MimeType::Gif => DataType::Gif,
MimeType::Jpeg => DataType::Jpeg,
MimeType::Png => DataType::Png,
MimeType::Bmp => DataType::Bmp,
_ => DataType::Reserved,
}
}
}
impl DataType {
/// A data type can only occupy 24 bits
pub const MAX: u32 = 16_777_215;
}

View file

@ -1,6 +1,7 @@
pub(super) mod advisory_rating;
pub(super) mod atom;
pub(super) mod constants;
pub(super) mod data_type;
pub(super) mod read;
mod r#ref;
pub(crate) mod write;
@ -16,8 +17,9 @@ use crate::tag::{
};
use crate::util::flag_item;
use crate::util::io::{FileLike, Length, Truncate};
use atom::{AdvisoryRating, Atom, AtomData};
use advisory_rating::AdvisoryRating;
use atom::{Atom, AtomData};
use data_type::DataType;
use std::borrow::Cow;
use std::io::Write;
@ -374,7 +376,10 @@ impl Ilst {
fn extract_number(&self, fourcc: [u8; 4], expected_size: usize) -> Option<u16> {
if let Some(atom) = self.get(&AtomIdent::Fourcc(fourcc)) {
match atom.data().next() {
Some(AtomData::Unknown { code: 0, data }) if data.len() >= expected_size => {
Some(AtomData::Unknown {
code: DataType::Reserved,
data,
}) if data.len() >= expected_size => {
return Some(u16::from_be_bytes([
data[expected_size - 2],
data[expected_size - 1],
@ -603,7 +608,10 @@ impl SplitTag for Ilst {
ItemValue::Text(text)
},
// We have to special case track/disc numbers since they are stored together
AtomData::Unknown { code: 0, data } if Vec::len(data) >= 6 => {
AtomData::Unknown {
code: DataType::Reserved,
data,
} if Vec::len(data) >= 6 => {
if let AtomIdent::Fourcc(ref fourcc) = ident {
match fourcc {
b"trkn" => {
@ -686,7 +694,7 @@ impl MergeTag for SplitTagRemainder {
tag.atoms.push(Atom {
ident: AtomIdent::Fourcc(ident),
data: AtomDataStorage::Single(AtomData::Unknown {
code: 0,
code: DataType::Reserved,
data: vec![0, 0, current[0], current[1], total[0], total[1], 0, 0],
}),
})
@ -802,13 +810,13 @@ mod tests {
use crate::mp4::ilst::atom::AtomDataStorage;
use crate::mp4::ilst::TITLE;
use crate::mp4::read::AtomReader;
use crate::mp4::{AdvisoryRating, Atom, AtomData, AtomIdent, Ilst, Mp4File};
use crate::mp4::{AdvisoryRating, Atom, AtomData, AtomIdent, DataType, Ilst, Mp4File};
use crate::picture::{MimeType, Picture, PictureType};
use crate::prelude::*;
use crate::tag::utils::test_utils;
use crate::tag::utils::test_utils::read_path;
use crate::tag::{ItemValue, Tag, TagItem, TagType};
use crate::picture::{MimeType, Picture, PictureType};
use std::io::{Cursor, Read as _, Seek as _, Write as _};
fn read_ilst(path: &str, parse_mode: ParsingMode) -> Ilst {
@ -853,7 +861,7 @@ mod tests {
expected_tag.insert(Atom::new(
AtomIdent::Fourcc(*b"trkn"),
AtomData::Unknown {
code: 0,
code: DataType::Reserved,
data: vec![0, 0, 0, 1, 0, 0, 0, 0],
},
));
@ -862,7 +870,7 @@ mod tests {
expected_tag.insert(Atom::new(
AtomIdent::Fourcc(*b"disk"),
AtomData::Unknown {
code: 0,
code: DataType::Reserved,
data: vec![0, 0, 0, 1, 0, 2],
},
));
@ -997,7 +1005,7 @@ mod tests {
&ilst,
*b"trkn",
&AtomData::Unknown {
code: 0,
code: DataType::Reserved,
data: vec![0, 0, 0, 1, 0, 0, 0, 0],
},
);
@ -1005,7 +1013,7 @@ mod tests {
&ilst,
*b"disk",
&AtomData::Unknown {
code: 0,
code: DataType::Reserved,
data: vec![0, 0, 0, 1, 0, 2, 0, 0],
},
)
@ -1024,7 +1032,7 @@ mod tests {
&ilst,
*b"plID",
&AtomData::Unknown {
code: 21,
code: DataType::BeSignedInteger,
data: 88888_u64.to_be_bytes().to_vec(),
},
)
@ -1321,7 +1329,7 @@ mod tests {
let atom = Atom::new(
AtomIdent::Fourcc(*b"SMTH"),
AtomData::Unknown {
code: 0,
code: DataType::Reserved,
data: b"Meaningless Data".to_vec(),
},
);

View file

@ -1,12 +1,11 @@
use super::constants::{
BE_SIGNED_INTEGER, BE_UNSIGNED_INTEGER, BMP, JPEG, PNG, RESERVED, UTF16, UTF8,
};
use super::constants::WELL_KNOWN_TYPE_SET;
use super::data_type::DataType;
use super::{Atom, AtomData, AtomIdent, Ilst};
use crate::config::{ParseOptions, ParsingMode};
use crate::error::{LoftyError, Result};
use crate::id3::v1::constants::GENRES;
use crate::macros::{err, try_vec};
use crate::mp4::atom_info::AtomInfo;
use crate::mp4::atom_info::{AtomInfo, ATOM_HEADER_LEN};
use crate::mp4::ilst::atom::AtomDataStorage;
use crate::mp4::read::{skip_unneeded, AtomReader};
use crate::picture::{MimeType, Picture, PictureType};
@ -204,7 +203,7 @@ fn parse_data_inner<R>(
reader: &mut AtomReader<R>,
parsing_mode: ParsingMode,
atom_info: &AtomInfo,
) -> Result<Option<Vec<(u32, Vec<u8>)>>>
) -> Result<Option<Vec<(DataType, Vec<u8>)>>>
where
R: Read + Seek,
{
@ -237,13 +236,14 @@ where
break;
}
// We don't care about the version
let _version = reader.read_u8()?;
let Some(data_type) = parse_type_indicator(reader, parsing_mode)? else {
log::warn!("Skipping atom with unknown type set");
let remaining_atom_len = next_atom.len - (ATOM_HEADER_LEN + 1);
let mut flags = [0; 3];
reader.read_exact(&mut flags)?;
let flags = u32::from_be_bytes([0, flags[0], flags[1], flags[2]]);
reader.seek(SeekFrom::Current(remaining_atom_len as i64))?;
pos += remaining_atom_len;
continue;
};
// We don't care about the locale
reader.seek(SeekFrom::Current(4))?;
@ -254,7 +254,7 @@ where
if content_len > 0 {
let mut content = try_vec![0; content_len];
reader.read_exact(&mut content)?;
ret.push((flags, content));
ret.push((data_type, content));
} else {
log::warn!("Skipping empty \"data\" atom");
}
@ -268,7 +268,9 @@ where
"Skipping unexpected atom {actual_ident:?}, expected {expected_ident:?}",
actual_ident = next_atom.ident,
expected_ident = DATA_ATOM_IDENT
)
);
reader.seek(SeekFrom::Current((next_atom.len - 16) as i64))?;
},
},
}
@ -280,6 +282,29 @@ where
Ok(ret)
}
fn parse_type_indicator<R>(
reader: &mut AtomReader<R>,
parsing_mode: ParsingMode,
) -> Result<Option<DataType>>
where
R: Read + Seek,
{
// The type indicator is formed of four bytes split between two fields. The first byte indicates
// the set of types from which the type is drawn. The second through fourth byte forms the second
// field and its interpretation depends upon the value in the first field.
let type_set = reader.read_u8()?;
if type_set != WELL_KNOWN_TYPE_SET {
if parsing_mode == ParsingMode::Strict {
err!(BadAtom("Unknown type set in data atom"))
}
return Ok(None);
}
Ok(Some(DataType::from(reader.read_u24()?)))
}
fn parse_uint(bytes: &[u8]) -> Result<u32> {
Ok(match bytes.len() {
1 => u32::from(bytes[0]),
@ -317,15 +342,15 @@ where
let mut data = Vec::new();
let len = atom_data.len();
for (flags, value) in atom_data {
let mime_type = match flags {
for (data_type, value) in atom_data {
let mime_type = match data_type {
// Type 0 is implicit
RESERVED => None,
DataType::Reserved => None,
// GIF is deprecated
12 => Some(MimeType::Gif),
JPEG => Some(MimeType::Jpeg),
PNG => Some(MimeType::Png),
BMP => Some(MimeType::Bmp),
DataType::Gif => Some(MimeType::Gif),
DataType::Jpeg => Some(MimeType::Jpeg),
DataType::Png => Some(MimeType::Png),
DataType::Bmp => Some(MimeType::Bmp),
_ => err!(BadAtom("\"covr\" atom has an unknown type")),
};
@ -357,13 +382,13 @@ where
Ok(())
}
fn interpret_atom_content(flags: u32, content: Vec<u8>) -> Result<AtomData> {
fn interpret_atom_content(flags: DataType, content: Vec<u8>) -> Result<AtomData> {
// https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW35
Ok(match flags {
UTF8 => AtomData::UTF8(utf8_decode(content)?),
UTF16 => AtomData::UTF16(utf16_decode_bytes(&content, u16::from_be_bytes)?),
BE_SIGNED_INTEGER => AtomData::SignedInteger(parse_int(&content)?),
BE_UNSIGNED_INTEGER => AtomData::UnsignedInteger(parse_uint(&content)?),
DataType::Utf8 => AtomData::UTF8(utf8_decode(content)?),
DataType::Utf16 => AtomData::UTF16(utf16_decode_bytes(&content, u16::from_be_bytes)?),
DataType::BeSignedInteger => AtomData::SignedInteger(parse_int(&content)?),
DataType::BeUnsignedInteger => AtomData::UnsignedInteger(parse_uint(&content)?),
code => AtomData::Unknown {
code,
data: content,

View file

@ -1,3 +1,4 @@
use super::data_type::DataType;
use super::r#ref::IlstRef;
use crate::config::{ParseOptions, WriteOptions};
use crate::error::{FileEncodingError, LoftyError, Result};
@ -14,9 +15,6 @@ use crate::util::io::{FileLike, Length, Truncate};
use std::io::{Cursor, Seek, SeekFrom, Write};
use crate::mp4::constants::{
BE_SIGNED_INTEGER, BE_UNSIGNED_INTEGER, BMP, JPEG, PNG, RESERVED, UTF16, UTF8,
};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
// A "full" atom is a traditional length + identifier, followed by a version (1) and flags (3)
@ -678,8 +676,8 @@ where
{
for value in data {
match value {
AtomData::UTF8(text) => write_data(UTF8, text.as_bytes(), writer)?,
AtomData::UTF16(text) => write_data(UTF16, text.as_bytes(), writer)?,
AtomData::UTF8(text) => write_data(DataType::Utf8, text.as_bytes(), writer)?,
AtomData::UTF16(text) => write_data(DataType::Utf16, text.as_bytes(), writer)?,
AtomData::Picture(ref pic) => write_picture(pic, writer)?,
AtomData::SignedInteger(int) => write_signed_int(*int, writer)?,
AtomData::UnsignedInteger(uint) => write_unsigned_int(*uint, writer)?,
@ -692,7 +690,7 @@ where
}
fn write_signed_int(int: i32, writer: &mut AtomWriterCompanion<'_>) -> Result<()> {
write_int(BE_SIGNED_INTEGER, int.to_be_bytes(), 4, writer)
write_int(DataType::BeSignedInteger, int.to_be_bytes(), 4, writer)
}
fn bytes_to_occupy_uint(uint: u32) -> usize {
@ -710,7 +708,7 @@ fn bytes_to_occupy_uint(uint: u32) -> usize {
fn write_unsigned_int(uint: u32, writer: &mut AtomWriterCompanion<'_>) -> Result<()> {
let bytes_needed = bytes_to_occupy_uint(uint);
write_int(
BE_UNSIGNED_INTEGER,
DataType::BeUnsignedInteger,
uint.to_be_bytes(),
bytes_needed,
writer,
@ -718,7 +716,7 @@ fn write_unsigned_int(uint: u32, writer: &mut AtomWriterCompanion<'_>) -> Result
}
fn write_int(
flags: u32,
flags: DataType,
bytes: [u8; 4],
bytes_needed: usize,
writer: &mut AtomWriterCompanion<'_>,
@ -728,18 +726,23 @@ fn write_int(
}
fn write_bool(b: bool, writer: &mut AtomWriterCompanion<'_>) -> Result<()> {
write_int(BE_SIGNED_INTEGER, i32::from(b).to_be_bytes(), 1, writer)
write_int(
DataType::BeSignedInteger,
i32::from(b).to_be_bytes(),
1,
writer,
)
}
fn write_picture(picture: &Picture, writer: &mut AtomWriterCompanion<'_>) -> Result<()> {
match picture.mime_type {
// GIF is deprecated
Some(MimeType::Gif) => write_data(12, &picture.data, writer),
Some(MimeType::Jpeg) => write_data(JPEG, &picture.data, writer),
Some(MimeType::Png) => write_data(PNG, &picture.data, writer),
Some(MimeType::Bmp) => write_data(BMP, &picture.data, writer),
Some(MimeType::Gif) => write_data(DataType::Gif, &picture.data, writer),
Some(MimeType::Jpeg) => write_data(DataType::Jpeg, &picture.data, writer),
Some(MimeType::Png) => write_data(DataType::Png, &picture.data, writer),
Some(MimeType::Bmp) => write_data(DataType::Bmp, &picture.data, writer),
// We'll assume implicit (0) was the intended type
None => write_data(RESERVED, &picture.data, writer),
None => write_data(DataType::Reserved, &picture.data, writer),
_ => Err(FileEncodingError::new(
FileType::Mp4,
"Attempted to write an unsupported picture format",
@ -748,8 +751,8 @@ fn write_picture(picture: &Picture, writer: &mut AtomWriterCompanion<'_>) -> Res
}
}
fn write_data(flags: u32, data: &[u8], writer: &mut AtomWriterCompanion<'_>) -> Result<()> {
if flags > 16_777_215 {
fn write_data(flags: DataType, data: &[u8], writer: &mut AtomWriterCompanion<'_>) -> Result<()> {
if u32::from(flags) > DataType::MAX {
return Err(FileEncodingError::new(
FileType::Mp4,
"Attempted to write a code that cannot fit in 24 bits",

View file

@ -23,8 +23,9 @@ pub mod constants {
pub use crate::mp4::properties::{AudioObjectType, Mp4Codec, Mp4Properties};
pub use atom_info::AtomIdent;
pub use ilst::atom::{AdvisoryRating, Atom, AtomData};
pub use ilst::advisory_rating::AdvisoryRating;
pub use ilst::atom::{Atom, AtomData};
pub use ilst::data_type::DataType;
pub use ilst::Ilst;
pub(crate) use properties::SAMPLE_RATES;