Bug 1726410 - Update mp4parse-rust to 62aa5d4. r=kinetik

Differential Revision: https://phabricator.services.mozilla.com/D122985
This commit is contained in:
Jon Bauman 2021-08-18 22:08:15 +00:00
parent 9cdc788c42
commit 58d94ab547
18 changed files with 292 additions and 94 deletions

View File

@ -20,7 +20,7 @@ tag = "v0.4.30"
[source."https://github.com/mozilla/mp4parse-rust"]
git = "https://github.com/mozilla/mp4parse-rust"
replace-with = "vendored-sources"
rev = "5326af6b54cec885cdb9e7be282a6db6e757b964"
rev = "62aa5d4e46289351ebfa2712668077ba8aa81064"
[source."https://github.com/mozilla/l10nregistry-rs"]
git = "https://github.com/mozilla/l10nregistry-rs"

4
Cargo.lock generated
View File

@ -3264,7 +3264,7 @@ dependencies = [
[[package]]
name = "mp4parse"
version = "0.11.5"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=5326af6b54cec885cdb9e7be282a6db6e757b964#5326af6b54cec885cdb9e7be282a6db6e757b964"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=62aa5d4e46289351ebfa2712668077ba8aa81064#62aa5d4e46289351ebfa2712668077ba8aa81064"
dependencies = [
"bitreader",
"byteorder",
@ -3282,7 +3282,7 @@ version = "0.1.0"
[[package]]
name = "mp4parse_capi"
version = "0.11.5"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=5326af6b54cec885cdb9e7be282a6db6e757b964#5326af6b54cec885cdb9e7be282a6db6e757b964"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=62aa5d4e46289351ebfa2712668077ba8aa81064#62aa5d4e46289351ebfa2712668077ba8aa81064"
dependencies = [
"byteorder",
"fallible_collections",

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"c06a8bf810a588465e8d26852c29ebb1fdf7e7adc1ee3cbac8a487ae92c38000","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"86cb40854b93f988e3a63ce6fe39d2ce95367f8ca301a5ba50676ff98a0ad791","benches/avif_benchmark.rs":"cd99c0dde025ab40d2cd860f53dc697a1587a48c164c3e5c8adfd40add29d772","src/boxes.rs":"50eed905feb775a1e696a6faa33233e8f8803591bfa9c5ad15ea02cbd17732d6","src/lib.rs":"d24a97ca6dfb25d672b28ba2e9da31923136b4f1783ceca4b96c745a7bc1be51","src/macros.rs":"76c840f9299797527fe71aa5b378ffb01312767372b45cc62deddb19775400ae","src/tests.rs":"87a391c2383f601439bf1ebebb3b24d998252e2574dde75c7c578fae9bfc27bb","src/unstable.rs":"c2cef9a3b2b08a4da66fa0305fce7a117bd99c9b8d57b0a044e1d99dbda6faf5","tests/1x1-black-alpha-50pct-premultiplied.avif":"31a8c235bf2cf601a593a7bc33f7f2779f2d5b2e0cd145897b931fce94b0c0b8","tests/amr_nb_1f.3gp":"d1423e3414ad06b69f8b58d5c916ec353ba2d0402d99dec9f1c88acc33b6a127","tests/amr_wb_1f.3gp":"be635b24097e8757b0c04d70ab28e00417ca113e86108b6c269b79b64b89bcd5","tests/bbb_sunflower_QCIF_30fps_h263_noaudio_1f.3gp":"03e5b1264d0a188d77b9e676ba3ce23a801b17aaa11c0343dfd851d6ea4e3a40","tests/clap-basic-1_3x3-to-1x1.avif":"83af9c8196fa93b2475163585a23d0eb5a8f8015d0db8da7a5d6de61adfb1876","tests/clusterfuzz-testcase-minimized-mp4-6093954524250112":"af7044a470732d4e7e34ac7ab5ff038c58b66f09702cbcd774931d7766bbfd35","tests/corrupt/av1C-missing-essential.avif":"a1501254c4071847b2269fe40b81409c389ff14e91cf7c0005a47e6ea97a6803","tests/corrupt/bad-ipma-flags.avif":"ecde7997b97db1910b9dcc7ca8e3c8957da0e83681ea9008c66dc9f12b78ad19","tests/corrupt/bad-ipma-version.avif":"7f9a1a0b4ebbf8d800d22eaae5ff78970cc6b811317db6c1467c6883952b7c9b","tests/corrupt/bug-1655846.avif":"e0a5a06225800fadf05f5352503a4cec11af73eef705c43b4acab5f4a99dea50","tests/corrupt/bug-1661347.avif":"31c26561e1d9eafb60f7c5968b82a0859d203d73f17f26b29276256acee12966","tests/corrupt/hdlr-not-first.avif":"2c29308af077209b9c984921b7e36f8fb7ca7cf379cf8eba4c7a91f65bc7a304","tests/corrupt/hdlr-not-pict.avif":"9fe37619606645a95725300a9e34fada9190d1e0b3919881db84353941ca9291","tests/corrupt/imir-before-clap.avif":"22d6b5dacf0ef0be59053beba7564b08037fed859ada2885e3476e0ff0d19c95","tests/corrupt/imir-missing-essential.avif":"b1226e4b1358528befbd3f1126b5caf0c5051b4354777b87e71f6001f3829f87","tests/corrupt/ipma-duplicate-item_id.avif":"ca8c5275b0b8b79c1068489a52d0a5c8f0b4453463971e72b694189f11c10745","tests/corrupt/ipma-duplicate-version-and-flags.avif":"cf8e15ec4b210235f3d68332a1adeb64e35c41b8d8e1e7586ae38b6d9cd8926c","tests/corrupt/ipma-invalid-property-index.avif":"2480e773fa716d22883032d05fd4cf2c6b00fba8796cf4ff286a5d1ba26adff6","tests/corrupt/irot-missing-essential.avif":"b7da1fc1d1b45bb1b7ca3494476e052f711d794a6d010df6870872ed8b9da10e","tests/corrupt/no-alpha-av1C.avif":"ad3d34d6331db7d9bea0c5f37efb88923520e33e08e7c636a5df435a4575eae7","tests/corrupt/no-av1C.avif":"eeb4fc50930c91465999f787c4a2a3b12de20556da0857be72da5a1a9eaa3f01","tests/corrupt/no-hdlr.avif":"91a1eb70c7b6adf2104e471d7deeeb98084a591d64ce09ba106c27edfbc3a409","tests/corrupt/no-ispe.avif":"4b6edfd8c9b40c25dc40305a6057e32b5e65f40da4a9d810c58dbff53254113f","tests/corrupt/no-mif1.avif":"1442aa6ffaeb9512724287768bfd1850d3aa29a651ef05abb33e5dec2b3ee5c2","tests/corrupt/no-pixi-for-alpha.avif":"f8adc3573c79ee25bf6d4dd2693c61661469b28f86a5c7b1d9e41b0e8d2d53bb","tests/corrupt/no-pixi.avif":"4b1776def440dc8b913c170e4479772ee6bbb299b8679f7c564704bd03c9597e","tests/multiple-extents.avif":"b5549ac68793e155a726d754e565cea0da03fa17833d3545f45c79e13f4c9360","tests/overflow.rs":"16b591d8def1a155b3b997622f6ea255536870d99c3d8f97c51755b77a50de3c","tests/public.rs":"38f046cebbfcb7e34a816b585282887acafe68dc5143dad1841fae6328677cc3","tests/valid-alpha.avif":"9d417a35b9b62ad3ff66ffbc55f16552aacf821a092aa5ef4adff7e746bd4c2f","tests/valid.avif":"f0b33e09bf01232e0877df325f47986c0bee7764f2a81c9c908ae109e7dc63c4"},"package":null}
{"files":{"Cargo.toml":"3969c05e1a5ba7f937776863571b7af940d8a2915ba5a7853c5760a2d71b14b1","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"86cb40854b93f988e3a63ce6fe39d2ce95367f8ca301a5ba50676ff98a0ad791","benches/avif_benchmark.rs":"cd99c0dde025ab40d2cd860f53dc697a1587a48c164c3e5c8adfd40add29d772","src/boxes.rs":"7f2236372a84991def6652d5fb3966411632418617c65c4e96ba544f94816c4d","src/lib.rs":"ccf889f955c275ae2179cff4ab7b43ba9f974571ce669a11bcac77f8b4812243","src/macros.rs":"76c840f9299797527fe71aa5b378ffb01312767372b45cc62deddb19775400ae","src/tests.rs":"87a391c2383f601439bf1ebebb3b24d998252e2574dde75c7c578fae9bfc27bb","src/unstable.rs":"c2cef9a3b2b08a4da66fa0305fce7a117bd99c9b8d57b0a044e1d99dbda6faf5","tests/1x1-black-alpha-50pct-premultiplied.avif":"31a8c235bf2cf601a593a7bc33f7f2779f2d5b2e0cd145897b931fce94b0c0b8","tests/amr_nb_1f.3gp":"d1423e3414ad06b69f8b58d5c916ec353ba2d0402d99dec9f1c88acc33b6a127","tests/amr_wb_1f.3gp":"be635b24097e8757b0c04d70ab28e00417ca113e86108b6c269b79b64b89bcd5","tests/av1C-missing-essential.avif":"a1501254c4071847b2269fe40b81409c389ff14e91cf7c0005a47e6ea97a6803","tests/bad-ipma-flags.avif":"ecde7997b97db1910b9dcc7ca8e3c8957da0e83681ea9008c66dc9f12b78ad19","tests/bad-ipma-version.avif":"7f9a1a0b4ebbf8d800d22eaae5ff78970cc6b811317db6c1467c6883952b7c9b","tests/bbb_sunflower_QCIF_30fps_h263_noaudio_1f.3gp":"03e5b1264d0a188d77b9e676ba3ce23a801b17aaa11c0343dfd851d6ea4e3a40","tests/clap-basic-1_3x3-to-1x1.avif":"83af9c8196fa93b2475163585a23d0eb5a8f8015d0db8da7a5d6de61adfb1876","tests/clusterfuzz-testcase-minimized-mp4-6093954524250112":"af7044a470732d4e7e34ac7ab5ff038c58b66f09702cbcd774931d7766bbfd35","tests/corrupt/bug-1655846.avif":"e0a5a06225800fadf05f5352503a4cec11af73eef705c43b4acab5f4a99dea50","tests/corrupt/bug-1661347.avif":"31c26561e1d9eafb60f7c5968b82a0859d203d73f17f26b29276256acee12966","tests/corrupt/hdlr-not-first.avif":"2c29308af077209b9c984921b7e36f8fb7ca7cf379cf8eba4c7a91f65bc7a304","tests/corrupt/hdlr-not-pict.avif":"9fe37619606645a95725300a9e34fada9190d1e0b3919881db84353941ca9291","tests/corrupt/imir-before-clap.avif":"22d6b5dacf0ef0be59053beba7564b08037fed859ada2885e3476e0ff0d19c95","tests/corrupt/ipma-duplicate-item_id.avif":"ca8c5275b0b8b79c1068489a52d0a5c8f0b4453463971e72b694189f11c10745","tests/corrupt/ipma-duplicate-version-and-flags.avif":"cf8e15ec4b210235f3d68332a1adeb64e35c41b8d8e1e7586ae38b6d9cd8926c","tests/corrupt/ipma-invalid-property-index.avif":"2480e773fa716d22883032d05fd4cf2c6b00fba8796cf4ff286a5d1ba26adff6","tests/corrupt/no-alpha-av1C.avif":"ad3d34d6331db7d9bea0c5f37efb88923520e33e08e7c636a5df435a4575eae7","tests/corrupt/no-av1C.avif":"eeb4fc50930c91465999f787c4a2a3b12de20556da0857be72da5a1a9eaa3f01","tests/corrupt/no-hdlr.avif":"91a1eb70c7b6adf2104e471d7deeeb98084a591d64ce09ba106c27edfbc3a409","tests/corrupt/no-ispe.avif":"4b6edfd8c9b40c25dc40305a6057e32b5e65f40da4a9d810c58dbff53254113f","tests/corrupt/no-pixi-for-alpha.avif":"f8adc3573c79ee25bf6d4dd2693c61661469b28f86a5c7b1d9e41b0e8d2d53bb","tests/corrupt/no-pixi.avif":"4b1776def440dc8b913c170e4479772ee6bbb299b8679f7c564704bd03c9597e","tests/imir-missing-essential.avif":"b1226e4b1358528befbd3f1126b5caf0c5051b4354777b87e71f6001f3829f87","tests/irot-missing-essential.avif":"b7da1fc1d1b45bb1b7ca3494476e052f711d794a6d010df6870872ed8b9da10e","tests/multiple-extents.avif":"b5549ac68793e155a726d754e565cea0da03fa17833d3545f45c79e13f4c9360","tests/no-mif1.avif":"1442aa6ffaeb9512724287768bfd1850d3aa29a651ef05abb33e5dec2b3ee5c2","tests/overflow.rs":"16b591d8def1a155b3b997622f6ea255536870d99c3d8f97c51755b77a50de3c","tests/public.rs":"2d8e32c56c0233bf983311de1fb13314543157deda79625bf65a727d01d4fa8b","tests/valid-alpha.avif":"9d417a35b9b62ad3ff66ffbc55f16552aacf821a092aa5ef4adff7e746bd4c2f","tests/valid.avif":"f0b33e09bf01232e0877df325f47986c0bee7764f2a81c9c908ae109e7dc63c4"},"package":null}

View File

@ -40,6 +40,7 @@ walkdir = "2.3.1"
criterion = "0.3"
[features]
missing-pixi-permitted = []
3gpp = []
meta-xml = []
unstable-api = []

View File

@ -126,6 +126,9 @@ box_database!(
CleanApertureBox 0x636c_6170, // "clap"
ImageRotation 0x6972_6f74, // "irot"
ImageMirror 0x696d_6972, // "imir"
OperatingPointSelectorProperty 0x6131_6f70, // "a1op"
AV1LayeredImageIndexingProperty 0x6131_6c78, // "a1lx"
LayerSelectorProperty 0x6c73_656c, // "lsel"
SampleTableBox 0x7374_626c, // "stbl"
SampleDescriptionBox 0x7374_7364, // "stsd"
TimeToSampleBox 0x7374_7473, // "stts"

View File

@ -148,6 +148,87 @@ struct HashMap;
#[allow(dead_code)]
struct String;
/// The return value to the C API
/// Any detail that needs to be communicated to the caller must be encoded here
/// since the [`Error`] type's associated data is part of the FFI.
#[repr(C)]
#[derive(PartialEq, Debug)]
pub enum Status {
Ok = 0,
BadArg = 1,
Invalid = 2,
Unsupported = 3,
Eof = 4,
Io = 5,
Oom = 6,
UnsupportedA1lx,
UnsupportedA1op,
UnsupportedClap,
UnsupportedGrid,
UnsupportedIpro,
UnsupportedLsel,
}
/// For convenience of creating an error for an unsupported feature which we
/// want to communicate the specific feature back to the C API caller
impl From<Status> for Error {
fn from(parse_status: Status) -> Self {
let msg = match parse_status {
Status::Ok
| Status::BadArg
| Status::Invalid
| Status::Unsupported
| Status::Eof
| Status::Io
| Status::Oom => {
panic!("Status -> Error is only for Status:UnsupportedXXX errors")
}
Status::UnsupportedA1lx => "AV1 layered image indexing (a1lx) is unsupported",
Status::UnsupportedA1op => "Operating point selection (a1op) is unsupported",
Status::UnsupportedClap => "Clean aperture (clap) transform is unsupported",
Status::UnsupportedGrid => "Grid-based images are unsupported",
Status::UnsupportedIpro => "Item protection (ipro) is unsupported",
Status::UnsupportedLsel => "Layer selection (lsel) is unsupported",
};
Self::UnsupportedDetail(parse_status, msg)
}
}
impl From<Error> for Status {
fn from(error: Error) -> Self {
match error {
Error::NoMoov | Error::InvalidData(_) => Self::Invalid,
Error::Unsupported(_) => Self::Unsupported,
Error::UnsupportedDetail(parse_status, _msg) => parse_status,
Error::UnexpectedEOF => Self::Eof,
Error::Io(_) => {
// Getting std::io::ErrorKind::UnexpectedEof is normal
// but our From trait implementation should have converted
// those to our Error::UnexpectedEOF variant.
Self::Io
}
Error::OutOfMemory => Self::Oom,
}
}
}
impl From<Result<(), Status>> for Status {
fn from(result: Result<(), Status>) -> Self {
match result {
Ok(()) => Status::Ok,
Err(Status::Ok) => unreachable!(),
Err(e) => e,
}
}
}
impl From<fallible_collections::TryReserveError> for Status {
fn from(_: fallible_collections::TryReserveError) -> Self {
Status::Oom
}
}
/// Describes parser failures.
///
/// This enum wraps the standard `io::Error` type, unified with
@ -158,6 +239,10 @@ pub enum Error {
InvalidData(&'static str),
/// Parse error caused by limited parser support rather than invalid data.
Unsupported(&'static str),
/// Similar to [`Self::Unsupported`], but for errors that have a specific
/// [`Status`] variant for communicating the detail across FFI.
/// See the helper [`From<Status> for Error`](enum.Error.html#impl-From<Status>)
UnsupportedDetail(Status, &'static str),
/// Reflect `std::io::ErrorKind::UnexpectedEof` for short data.
UnexpectedEOF,
/// Propagate underlying errors from `std::io`.
@ -483,7 +568,7 @@ pub struct VPxConfigBox {
pub codec_init: TryVec<u8>,
}
/// See AV1-ISOBMFF § 2.3.3 https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox-syntax
/// See [AV1-ISOBMFF § 2.3.3](https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox-syntax)
#[derive(Debug)]
pub struct AV1ConfigBox {
pub profile: u8,
@ -502,7 +587,6 @@ pub struct AV1ConfigBox {
}
impl AV1ConfigBox {
/// See https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox-syntax
const CONFIG_OBUS_OFFSET: usize = 4;
pub fn config_obus(&self) -> &[u8] {
@ -1711,8 +1795,16 @@ pub fn read_avif<T: Read>(f: &mut T, strictness: ParseStrictness) -> Result<Avif
.map_or(false, |opt| opt.is_some())
};
if !has_pixi(primary_item_id) || !alpha_item_id.map_or(true, has_pixi) {
// The requirement to include pixi is in the process of being changed
// to allowing its omission to imply a default value. In anticipation
// of that, only give an error in strict mode
// See https://github.com/MPEGGroup/MIAF/issues/9
fail_if(
strictness != ParseStrictness::Permissive,
if cfg!(feature = "missing-pixi-permitted") {
strictness == ParseStrictness::Strict
} else {
strictness != ParseStrictness::Permissive
},
"The pixel information property shall be associated with every image \
that is displayable (not hidden) \
per MIAF (ISO/IEC 23000-22:2019) specification § 7.3.6.6",
@ -1850,9 +1942,15 @@ fn read_avif_meta<T: Read + Offset>(
let item_infos = item_infos.ok_or(Error::InvalidData("iinf missing"))?;
if let Some(item_info) = item_infos.iter().find(|x| x.item_id == primary_item_id) {
if &item_info.item_type.to_be_bytes() != b"av01" {
warn!("primary_item_id type: {}", U32BE(item_info.item_type));
return Err(Error::InvalidData("primary_item_id type is not av01"));
debug!("primary_item_id type: {}", U32BE(item_info.item_type));
match &item_info.item_type.to_be_bytes() {
b"av01" => {}
b"grid" => return Err(Error::from(Status::UnsupportedGrid)),
_ => {
return Err(Error::InvalidData(
"primary_item_id type is neither 'av01' nor 'grid'",
))
}
}
} else {
return Err(Error::InvalidData(
@ -1957,9 +2055,7 @@ fn read_infe<T: Read>(src: &mut BMFFBox<T>, strictness: ParseStrictness) -> Resu
let item_protection_index = be_u16(src)?;
if item_protection_index != 0 {
return Err(Error::Unsupported(
"protected items (infe.item_protection_index != 0) are not supported",
));
return Err(Error::from(Status::UnsupportedIpro));
}
let item_type = be_u32(src)?;
@ -2102,6 +2198,9 @@ fn read_iprp<T: Read>(
| ItemProperty::Rotation(_) => {
if !a.essential {
warn!("{:?} is invalid", property);
// This is a "shall", but it is likely to change, so only
// fail if using strict parsing.
// See https://github.com/mozilla/mp4parse-rust/issues/284
fail_if(
strictness == ParseStrictness::Strict,
"All transformative properties associated with coded and \
@ -2525,6 +2624,11 @@ fn read_ipma<T: Read>(
/// Parse an ItemPropertyContainerBox
///
/// For unsupported properties that we know about, return specific
/// [`Status`] UnsupportedXXXX variants. Unless running in
/// [`ParseStrictness::Permissive`] mode, in which case, unsupported properties
/// will be ignored.
///
/// See ISOBMFF (ISO 14496-12:2020 § 8.11.14.1
fn read_ipco<T: Read>(
src: &mut BMFFBox<T>,
@ -2538,6 +2642,14 @@ fn read_ipco<T: Read>(
if let Some(property) = match b.head.name {
BoxType::AuxiliaryTypeProperty => Some(ItemProperty::AuxiliaryType(read_auxc(&mut b)?)),
BoxType::AV1CodecConfigurationBox => Some(ItemProperty::AV1Config(read_av1c(&mut b)?)),
BoxType::AV1LayeredImageIndexingProperty
if strictness != ParseStrictness::Permissive =>
{
return Err(Error::from(Status::UnsupportedA1lx))
}
BoxType::CleanApertureBox if strictness != ParseStrictness::Permissive => {
return Err(Error::from(Status::UnsupportedClap))
}
BoxType::ColourInformationBox => {
Some(ItemProperty::Colour(read_colr(&mut b, strictness)?))
}
@ -2546,6 +2658,14 @@ fn read_ipco<T: Read>(
BoxType::ImageSpatialExtentsProperty => {
Some(ItemProperty::ImageSpatialExtents(read_ispe(&mut b)?))
}
BoxType::LayerSelectorProperty if strictness != ParseStrictness::Permissive => {
return Err(Error::from(Status::UnsupportedLsel))
}
BoxType::OperatingPointSelectorProperty
if strictness != ParseStrictness::Permissive =>
{
return Err(Error::from(Status::UnsupportedA1op))
}
BoxType::PixelInformationBox => Some(ItemProperty::Channels(read_pixi(&mut b)?)),
other_box_type => {
// Though we don't do anything with other property types, we still store
@ -3733,7 +3853,7 @@ fn read_vpcc<T: Read>(src: &mut BMFFBox<T>) -> Result<VPxConfigBox> {
})
}
/// See AV1-ISOBMFF § 2.3.3 https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox-syntax
/// See [AV1-ISOBMFF § 2.3.3](https://aomediacodec.github.io/av1-isobmff/#av1codecconfigurationbox-syntax)
fn read_av1c<T: Read>(src: &mut BMFFBox<T>) -> Result<AV1ConfigBox> {
// We want to store the raw config as well as a structured (parsed) config, so create a copy of
// the raw config so we have it later, and then parse the structured data from that.
@ -4124,7 +4244,7 @@ fn read_esds<T: Read>(src: &mut BMFFBox<T>) -> Result<ES_Descriptor> {
}
/// Parse `FLACSpecificBox`.
/// See https://github.com/xiph/flac/blob/master/doc/isoflac.txt § 3.3.2
/// See [Encapsulation of FLAC in ISO Base Media File Format](https://github.com/xiph/flac/blob/master/doc/isoflac.txt) § 3.3.2
fn read_dfla<T: Read>(src: &mut BMFFBox<T>) -> Result<FLACSpecificBox> {
let (version, flags) = read_fullbox_extra(src)?;
if version != 0 {

View File

@ -9,7 +9,6 @@ use mp4::ParseStrictness;
use std::convert::TryInto;
use std::fs::File;
use std::io::{Cursor, Read, Seek, SeekFrom};
use std::path::Path;
static MINI_MP4: &str = "tests/minimal.mp4";
static MINI_MP4_WITH_METADATA: &str = "tests/metadata.mp4";
@ -38,8 +37,8 @@ static IMAGE_AVIF_ALPHA: &str = "tests/valid-alpha.avif";
static IMAGE_AVIF_ALPHA_PREMULTIPLIED: &str = "tests/1x1-black-alpha-50pct-premultiplied.avif";
static IMAGE_AVIF_CORRUPT: &str = "tests/corrupt/bug-1655846.avif";
static IMAGE_AVIF_CORRUPT_2: &str = "tests/corrupt/bug-1661347.avif";
static IMAGE_AVIF_IPMA_BAD_VERSION: &str = "tests/corrupt/bad-ipma-version.avif";
static IMAGE_AVIF_IPMA_BAD_FLAGS: &str = "tests/corrupt/bad-ipma-flags.avif";
static IMAGE_AVIF_IPMA_BAD_VERSION: &str = "tests/bad-ipma-version.avif";
static IMAGE_AVIF_IPMA_BAD_FLAGS: &str = "tests/bad-ipma-flags.avif";
static IMAGE_AVIF_IPMA_DUPLICATE_VERSION_AND_FLAGS: &str =
"tests/corrupt/ipma-duplicate-version-and-flags.avif";
static IMAGE_AVIF_IPMA_DUPLICATE_ITEM_ID: &str = "tests/corrupt/ipma-duplicate-item_id.avif";
@ -48,24 +47,48 @@ static IMAGE_AVIF_IPMA_INVALID_PROPERTY_INDEX: &str =
static IMAGE_AVIF_NO_HDLR: &str = "tests/corrupt/hdlr-not-first.avif";
static IMAGE_AVIF_HDLR_NOT_FIRST: &str = "tests/corrupt/no-hdlr.avif";
static IMAGE_AVIF_HDLR_NOT_PICT: &str = "tests/corrupt/hdlr-not-pict.avif";
static IMAGE_AVIF_NO_MIF1: &str = "tests/corrupt/no-mif1.avif";
static IMAGE_AVIF_NO_MIF1: &str = "tests/no-mif1.avif";
static IMAGE_AVIF_NO_PIXI: &str = "tests/corrupt/no-pixi.avif";
static IMAGE_AVIF_NO_AV1C: &str = "tests/corrupt/no-av1C.avif";
static IMAGE_AVIF_NO_ISPE: &str = "tests/corrupt/no-ispe.avif";
static IMAGE_AVIF_NO_ALPHA_AV1C: &str = "tests/corrupt/no-alpha-av1C.avif";
static IMAGE_AVIF_NO_ALPHA_PIXI: &str = "tests/corrupt/no-pixi-for-alpha.avif";
static IMAGE_AVIF_AV1C_MISSING_ESSENTIAL: &str = "tests/corrupt/av1C-missing-essential.avif";
static IMAGE_AVIF_IMIR_MISSING_ESSENTIAL: &str = "tests/corrupt/imir-missing-essential.avif";
static IMAGE_AVIF_IROT_MISSING_ESSENTIAL: &str = "tests/corrupt/irot-missing-essential.avif";
static IMAGE_AVIF_GRID: &str = "av1-avif/testFiles/Microsoft/Summer_in_Tomsk_720p_5x4_grid.avif";
static IMAGE_AVIF_AV1C_MISSING_ESSENTIAL: &str = "tests/av1C-missing-essential.avif";
static IMAGE_AVIF_IMIR_MISSING_ESSENTIAL: &str = "tests/imir-missing-essential.avif";
static IMAGE_AVIF_IROT_MISSING_ESSENTIAL: &str = "tests/irot-missing-essential.avif";
static AVIF_TEST_DIRS: &[&str] = &["tests", "av1-avif/testFiles"];
// TODO: file bug on https://github.com/AOMediaCodec/av1-avif
static AVIF_A1OP: &str =
"av1-avif/testFiles/Apple/multilayer_examples/animals_00_multilayer_a1op.avif";
static AVIF_A1LX: &str =
"av1-avif/testFiles/Apple/multilayer_examples/animals_00_multilayer_grid_a1lx.avif";
static AVIF_CLAP: &str = "tests/clap-basic-1_3x3-to-1x1.avif";
static AVIF_GRID: &str = "av1-avif/testFiles/Microsoft/Summer_in_Tomsk_720p_5x4_grid.avif";
static AVIF_LSEL: &str =
"av1-avif/testFiles/Apple/multilayer_examples/animals_00_multilayer_lsel.avif";
static AVIF_NO_PIXI_IMAGES: &[&str] = &[IMAGE_AVIF_NO_PIXI, IMAGE_AVIF_NO_ALPHA_PIXI];
static AVIF_UNSUPPORTED_IMAGES: &[&str] = &[
AVIF_A1OP,
AVIF_A1LX,
AVIF_CLAP,
AVIF_GRID,
AVIF_LSEL,
"av1-avif/testFiles/Apple/multilayer_examples/animals_00_multilayer_a1lx.avif",
"av1-avif/testFiles/Apple/multilayer_examples/animals_00_multilayer_a1op_lsel.avif",
"av1-avif/testFiles/Apple/multilayer_examples/animals_00_multilayer_grid_lsel.avif",
"av1-avif/testFiles/Xiph/abandoned_filmgrain.avif",
"av1-avif/testFiles/Xiph/fruits_2layer_thumbsize.avif",
"av1-avif/testFiles/Xiph/quebec_3layer_op2.avif",
"av1-avif/testFiles/Xiph/tiger_3layer_1res.avif",
"av1-avif/testFiles/Xiph/tiger_3layer_3res.avif",
];
/// See https://github.com/AOMediaCodec/av1-avif/issues/150
static AV1_AVIF_CORRUPT_IMAGES: &[&str] = &[
"av1-avif/testFiles/Microsoft/Chimera_10bit_cropped_to_1920x1008.avif",
"av1-avif/testFiles/Microsoft/Chimera_10bit_cropped_to_1920x1008_with_HDR_metadata.avif",
"av1-avif/testFiles/Microsoft/Chimera_8bit_cropped_480x256.avif",
"av1-avif/testFiles/Link-U/kimono.crop.avif",
"av1-avif/testFiles/Link-U/kimono.mirror-vertical.rotate270.crop.avif",
"av1-avif/testFiles/Netflix/avis/Chimera-AV1-10bit-480x270.avif",
];
static AVIF_CORRUPT_IMAGES_DIR: &str = "tests/corrupt";
// The 1 frame h263 3gp file can be generated by ffmpeg with command
@ -790,7 +813,7 @@ fn assert_invalid_data<T: std::fmt::Debug>(result: mp4::Result<T>, expected_msg:
Err(Error::InvalidData(msg)) if msg == expected_msg => {}
Err(Error::InvalidData(msg)) if msg != expected_msg => {
panic!(
"Error message mismtatch\nExpected: {}\nFound: {}",
"Error message mismatch\nExpected: {}\nFound: {}",
expected_msg, msg
);
}
@ -923,8 +946,14 @@ fn public_avif_pixi_present_for_displayable_images() {
let expected_msg = "The pixel information property shall be associated with every image \
that is displayable (not hidden) \
per MIAF (ISO/IEC 23000-22:2019) specification § 7.3.6.6";
assert_avif_shall(IMAGE_AVIF_NO_PIXI, expected_msg);
assert_avif_shall(IMAGE_AVIF_NO_ALPHA_PIXI, expected_msg);
let pixi_test = if cfg!(feature = "missing-pixi-permitted") {
assert_avif_should
} else {
assert_avif_shall
};
pixi_test(IMAGE_AVIF_NO_PIXI, expected_msg);
pixi_test(IMAGE_AVIF_NO_ALPHA_PIXI, expected_msg);
}
#[test]
@ -943,12 +972,66 @@ fn public_avif_ispe_present() {
assert_avif_shall(IMAGE_AVIF_NO_ISPE, expected_msg);
}
fn assert_unsupported<T: std::fmt::Debug>(result: mp4::Result<T>, expected_status: mp4::Status) {
match result {
Err(Error::UnsupportedDetail(status, _msg)) if status == expected_status => {}
Err(Error::UnsupportedDetail(status, _msg)) if status != expected_status => {
panic!(
"Error message mismatch\nExpected: {:?}\nFound: {:?}",
expected_status, status
);
}
r => panic!(
"Expected Err({:?}), found {:?}",
Error::from(expected_status),
r
),
}
}
#[test]
#[ignore] // Remove when we add support; see https://github.com/mozilla/mp4parse-rust/issues/198
fn public_avif_primary_item_is_grid() {
let input = &mut File::open(IMAGE_AVIF_GRID).expect("Unknown file");
mp4::read_avif(input, ParseStrictness::Normal).expect("read_avif failed");
// Add some additional checks
fn public_avif_a1lx() {
let input = &mut File::open(AVIF_A1LX).expect("Unknown file");
assert_unsupported(
mp4::read_avif(input, ParseStrictness::Normal),
mp4::Status::UnsupportedA1lx,
);
}
#[test]
fn public_avif_a1op() {
let input = &mut File::open(AVIF_A1OP).expect("Unknown file");
assert_unsupported(
mp4::read_avif(input, ParseStrictness::Normal),
mp4::Status::UnsupportedA1op,
);
}
#[test]
fn public_avif_clap() {
let input = &mut File::open(AVIF_CLAP).expect("Unknown file");
assert_unsupported(
mp4::read_avif(input, ParseStrictness::Normal),
mp4::Status::UnsupportedClap,
);
}
#[test]
fn public_avif_grid() {
let input = &mut File::open(AVIF_GRID).expect("Unknown file");
assert_unsupported(
mp4::read_avif(input, ParseStrictness::Normal),
mp4::Status::UnsupportedGrid,
);
}
#[test]
fn public_avif_lsel() {
let input = &mut File::open(AVIF_LSEL).expect("Unknown file");
assert_unsupported(
mp4::read_avif(input, ParseStrictness::Normal),
mp4::Status::UnsupportedLsel,
);
}
#[test]
@ -962,7 +1045,21 @@ fn public_avif_read_samples_strict() {
public_avif_read_samples_impl(ParseStrictness::Strict);
}
fn to_canonical_paths(strs: &[&str]) -> Vec<std::path::PathBuf> {
strs.iter()
.map(std::fs::canonicalize)
.map(Result::unwrap)
.collect()
}
fn public_avif_read_samples_impl(strictness: ParseStrictness) {
let corrupt_images = to_canonical_paths(AV1_AVIF_CORRUPT_IMAGES);
let unsupported_images = to_canonical_paths(AVIF_UNSUPPORTED_IMAGES);
let legal_no_pixi_images = if cfg!(feature = "missing-pixi-permitted") {
to_canonical_paths(AVIF_NO_PIXI_IMAGES)
} else {
vec![]
};
for dir in AVIF_TEST_DIRS {
for entry in walkdir::WalkDir::new(dir) {
let entry = entry.expect("AVIF entry");
@ -971,21 +1068,35 @@ fn public_avif_read_samples_impl(strictness: ParseStrictness) {
eprintln!("Skipping {:?}", path);
continue; // Skip directories, ReadMe.txt, etc.
}
if path.parent().unwrap() == Path::new(AVIF_CORRUPT_IMAGES_DIR) {
eprintln!("Skipping {:?}", path);
continue;
}
if AV1_AVIF_CORRUPT_IMAGES.contains(&path.to_str().unwrap()) {
eprintln!("Skipping invalid image from av1-avif repo: {:?}", path);
continue;
}
if path == Path::new(IMAGE_AVIF_GRID) {
eprintln!("Skipping {:?}", path);
continue; // Remove when public_avif_primary_item_is_grid passes
}
println!("parsing {:?}", path);
let corrupt = (path.canonicalize().unwrap().parent().unwrap()
== std::fs::canonicalize(AVIF_CORRUPT_IMAGES_DIR).unwrap()
|| corrupt_images.contains(&path.canonicalize().unwrap()))
&& !legal_no_pixi_images.contains(&path.canonicalize().unwrap());
let unsupported = unsupported_images.contains(&path.canonicalize().unwrap());
println!(
"parsing {}{}{:?}",
if corrupt { "(corrupt) " } else { "" },
if unsupported { "(unsupported) " } else { "" },
path,
);
let input = &mut File::open(path).expect("Unknow file");
mp4::read_avif(input, strictness).expect("read_avif failed");
match mp4::read_avif(input, strictness) {
Ok(_) if unsupported || corrupt => panic!("Expected error parsing {:?}", path),
Ok(_) => eprintln!("Successfully parsed {:?}", path),
Err(e @ Error::Unsupported(_)) | Err(e @ Error::UnsupportedDetail(..))
if unsupported =>
{
eprintln!(
"Expected error parsing unsupported input {:?}: {:?}",
path, e
)
}
Err(e) if corrupt => {
eprintln!("Expected error parsing corrupt input {:?}: {:?}", path, e)
}
Err(e) => panic!("Unexected error parsing {:?}: {:?}", path, e),
}
}
}
}

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"b0653020f28155bfce958504c81c9fde20175e31774e5e42250dc7d3bc5b9985","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"f776ed4bbb7b58a5684402a9c5c28dfe1fa02b6b184139b2c2c49384cc1e3723","cbindgen.toml":"d3241a7ccfcc4ea53f90b1b59941b28f345e6e6e29c264726b4cf99df672b4a7","examples/dump.rs":"268093925d28d1636e106d93a2f2917fb1d7ddaf04ecd70880e1551fb578de1a","src/lib.rs":"e7629d39c39f6b390219beb5ffb8d80484e37b82350067b15ef88eb2480b3c31","tests/test_chunk_out_of_range.rs":"b5da583218d98027ed973a29c67434a91a1306f2d2fb39ec4d640d4824c308ce","tests/test_encryption.rs":"b918f0f10e7708bff5fae4becf1d09a188db25d874d0919d509b90266504eed7","tests/test_fragment.rs":"e90eb5a4418d30002655466c0c4b3125c7fd70a74b6871471eaa172f1def9db8","tests/test_rotation.rs":"fb43c2f2dfa496d151c33bdd46c0fd3252387c23cc71e2cac9ed0234de715a81","tests/test_sample_table.rs":"19b8d0b0f7ed79a857329321b49f5a7f687901cadd4cd22bc6728febd919d3ce","tests/test_workaround_stsc.rs":"7dd419f3d55b9a3a039cac57e58a9240a9c8166bcd4356c24f69f731c3ced83b"},"package":null}
{"files":{"Cargo.toml":"fa0e2b46e9547dba9134da4001b2cd803fac58f9252394aa62653fe99bd220fa","LICENSE":"fab3dd6bdab226f1c08630b1dd917e11fcb4ec5e1e020e2c16f83a0a13863e85","README.md":"f776ed4bbb7b58a5684402a9c5c28dfe1fa02b6b184139b2c2c49384cc1e3723","cbindgen.toml":"f82065edc5be3d2e43db65ac67490194701b3800ce3d42976fc7ad351928a296","examples/dump.rs":"268093925d28d1636e106d93a2f2917fb1d7ddaf04ecd70880e1551fb578de1a","src/lib.rs":"7097c7e9a9f2852472897b19d1c14268aa6190b78609ae90a0c69a65de5538b8","tests/test_chunk_out_of_range.rs":"b5da583218d98027ed973a29c67434a91a1306f2d2fb39ec4d640d4824c308ce","tests/test_encryption.rs":"b918f0f10e7708bff5fae4becf1d09a188db25d874d0919d509b90266504eed7","tests/test_fragment.rs":"e90eb5a4418d30002655466c0c4b3125c7fd70a74b6871471eaa172f1def9db8","tests/test_rotation.rs":"fb43c2f2dfa496d151c33bdd46c0fd3252387c23cc71e2cac9ed0234de715a81","tests/test_sample_table.rs":"19b8d0b0f7ed79a857329321b49f5a7f687901cadd4cd22bc6728febd919d3ce","tests/test_workaround_stsc.rs":"7dd419f3d55b9a3a039cac57e58a9240a9c8166bcd4356c24f69f731c3ced83b"},"package":null}

View File

@ -34,6 +34,7 @@ num-traits = "0.2.14"
env_logger = "0.8"
[features]
missing-pixi-permitted = ["mp4parse/missing-pixi-permitted"]
3gpp = ["mp4parse/3gpp"]
meta-xml = ["mp4parse/meta-xml"]
mp4v = ["mp4parse/mp4v"]

View File

@ -25,9 +25,16 @@ rename_variants = "QualifiedScreamingSnakeCase"
parse_deps = true
include = ["mp4parse"]
[export]
# `mp4parse::Status` was previously defined as `mp4parse_capi::Mp4parseStatus`,
# but now is referenced from `mp4parse_capi` via `pub use mp4parse::Status as Mp4parseStatus`,
# the name `Status` does not appear in the public C API, so we must force its inclusion
include = ["Status"]
[export.rename]
# We need to declare these types in mp4parse, but we rename them in the generated
# header to match mp4parse_capi naming conventions
"Status" = "Mp4parseStatus"
"ParseStrictness" = "Mp4parseStrictness"
"ImageSpatialExtentsProperty" = "Mp4parseImageSpatialExtents"
"ImageRotation" = "Mp4parseIrot"

View File

@ -54,11 +54,11 @@ use mp4parse::unstable::{
use mp4parse::AudioCodecSpecific;
use mp4parse::AvifContext;
use mp4parse::CodecType;
use mp4parse::Error;
use mp4parse::MediaContext;
// Re-exported so consumers don't have to depend on mp4parse as well
pub use mp4parse::ParseStrictness;
use mp4parse::SampleEntry;
pub use mp4parse::Status as Mp4parseStatus;
use mp4parse::TrackType;
use mp4parse::TryBox;
use mp4parse::TryHashMap;
@ -75,18 +75,6 @@ struct HashMap;
#[allow(dead_code)]
struct String;
#[repr(C)]
#[derive(PartialEq, Debug)]
pub enum Mp4parseStatus {
Ok = 0,
BadArg = 1,
Invalid = 2,
Unsupported = 3,
Eof = 4,
Io = 5,
Oom = 6,
}
#[repr(C)]
#[derive(PartialEq, Debug)]
pub enum Mp4parseTrackType {
@ -518,39 +506,6 @@ fn mp4parse_new_common_safe<T: Read, P: ContextParser>(
.map_err(Mp4parseStatus::from)
}
impl From<mp4parse::Error> for Mp4parseStatus {
fn from(error: mp4parse::Error) -> Self {
match error {
Error::NoMoov | Error::InvalidData(_) => Mp4parseStatus::Invalid,
Error::Unsupported(_) => Mp4parseStatus::Unsupported,
Error::UnexpectedEOF => Mp4parseStatus::Eof,
Error::Io(_) => {
// Getting std::io::ErrorKind::UnexpectedEof is normal
// but our From trait implementation should have converted
// those to our Error::UnexpectedEOF variant.
Mp4parseStatus::Io
}
Error::OutOfMemory => Mp4parseStatus::Oom,
}
}
}
impl From<Result<(), Mp4parseStatus>> for Mp4parseStatus {
fn from(result: Result<(), Mp4parseStatus>) -> Self {
match result {
Ok(()) => Mp4parseStatus::Ok,
Err(Mp4parseStatus::Ok) => unreachable!(),
Err(e) => e,
}
}
}
impl From<fallible_collections::TryReserveError> for Mp4parseStatus {
fn from(_: fallible_collections::TryReserveError) -> Self {
Mp4parseStatus::Oom
}
}
/// Free an `Mp4parseParser*` allocated by `mp4parse_new()`.
///
/// # Safety

View File

@ -9,7 +9,7 @@ description = "Shared Rust code for libxul"
geckoservo = { path = "../../../../servo/ports/geckolib" }
kvstore = { path = "../../../components/kvstore" }
lmdb-rkv-sys = { version = "0.11", features = ["mdb_idl_logn_9"] }
mp4parse_capi = { git = "https://github.com/mozilla/mp4parse-rust", rev = "5326af6b54cec885cdb9e7be282a6db6e757b964" }
mp4parse_capi = { git = "https://github.com/mozilla/mp4parse-rust", rev = "62aa5d4e46289351ebfa2712668077ba8aa81064", features = ["missing-pixi-permitted"] }
nserror = { path = "../../../../xpcom/rust/nserror" }
nsstring = { path = "../../../../xpcom/rust/nsstring" }
netwerk_helper = { path = "../../../../netwerk/base/rust-helper" }