--- a/media/mp4parse-rust/mp4parse.h
+++ b/media/mp4parse-rust/mp4parse.h
@@ -11,27 +11,28 @@ extern "C" {
// THIS FILE IS AUTOGENERATED BY mp4parse_capi/build.rs - DO NOT EDIT
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
typedef enum {
- MP4PARSE_CODEC_UNKNOWN = 0,
- MP4PARSE_CODEC_AAC = 1,
- MP4PARSE_CODEC_FLAC = 2,
- MP4PARSE_CODEC_OPUS = 3,
- MP4PARSE_CODEC_AVC = 4,
- MP4PARSE_CODEC_VP9 = 5,
- MP4PARSE_CODEC_MP3 = 6,
- MP4PARSE_CODEC_MP4V = 7,
- MP4PARSE_CODEC_JPEG = 8,
- MP4PARSE_CODEC_AC3 = 9,
- MP4PARSE_CODEC_EC3 = 10,
+ MP4PARSE_CODEC_UNKNOWN,
+ MP4PARSE_CODEC_AAC,
+ MP4PARSE_CODEC_FLAC,
+ MP4PARSE_CODEC_OPUS,
+ MP4PARSE_CODEC_AVC,
+ MP4PARSE_CODEC_VP9,
+ MP4PARSE_CODEC_MP3,
+ MP4PARSE_CODEC_MP4V,
+ MP4PARSE_CODEC_JPEG,
+ MP4PARSE_CODEC_AC3,
+ MP4PARSE_CODEC_EC3,
+ MP4PARSE_CODEC_ALAC,
} Mp4parseCodec;
typedef enum {
MP4PARSE_STATUS_OK = 0,
MP4PARSE_STATUS_BAD_ARG = 1,
MP4PARSE_STATUS_INVALID = 2,
MP4PARSE_STATUS_UNSUPPORTED = 3,
MP4PARSE_STATUS_EOF = 4,
@@ -164,21 +165,16 @@ Mp4parseStatus mp4parse_get_track_video_
/*
* A fragmented file needs mvex table and contains no data in stts, stsc, and stco boxes.
*/
Mp4parseStatus mp4parse_is_fragmented(Mp4parseParser *parser,
uint32_t track_id,
uint8_t *fragmented);
/*
- * Enable `mp4_parser` log.
- */
-void mp4parse_log(bool enable);
-
-/*
* Allocate an `Mp4parseParser*` to read from the supplied `Mp4parseIo`.
*/
Mp4parseParser *mp4parse_new(const Mp4parseIo *io);
/*
* Run the `Mp4parseParser*` allocated by `mp4parse_new()` until EOF or error.
*/
Mp4parseStatus mp4parse_read(Mp4parseParser *parser);
--- a/media/mp4parse-rust/mp4parse/Cargo.toml
+++ b/media/mp4parse-rust/mp4parse/Cargo.toml
@@ -1,11 +1,11 @@
[package]
name = "mp4parse"
-version = "0.9.1"
+version = "0.10.0"
authors = [
"Ralph Giles <giles@mozilla.com>",
"Matthew Gregan <kinetik@flim.org>",
"Alfredo Yang <ayang@mozilla.com>",
]
description = "Parser for ISO base media file format (mp4)"
documentation = "https://docs.rs/mp4parse/"
@@ -16,16 +16,16 @@ repository = "https://github.com/mozilla
# Avoid complaints about trying to package test files.
exclude = [
"*.mp4",
]
[dependencies]
-byteorder = "1.0.0"
+byteorder = "1.2.1"
bitreader = { version = "0.3.0" }
-num-traits = "0.1.37"
+num-traits = "0.2.0"
mp4parse_fallible = { version = "0.0.1", optional = true }
+log = "0.4"
[dev-dependencies]
test-assembler = "0.1.2"
-
--- a/media/mp4parse-rust/mp4parse/src/boxes.rs
+++ b/media/mp4parse-rust/mp4parse/src/boxes.rs
@@ -133,9 +133,10 @@ box_database!(
ProtectionSystemSpecificHeaderBox 0x70737368, // "pssh"
SchemeInformationBox 0x73636869, // "schi"
TrackEncryptionBox 0x74656e63, // "tenc"
ProtectionSchemeInformationBox 0x73696e66, // "sinf"
OriginalFormatBox 0x66726d61, // "frma"
MP3AudioSampleEntry 0x2e6d7033, // ".mp3" - from F4V.
CompositionOffsetBox 0x63747473, // "ctts"
LPCMAudioSampleEntry 0x6C70636D, // "lpcm" - quicktime atom
+ ALACSpecificBox 0x616C6163, // "alac" - Also used by ALACSampleEntry
);
--- a/media/mp4parse-rust/mp4parse/src/lib.rs
+++ b/media/mp4parse-rust/mp4parse/src/lib.rs
@@ -1,16 +1,19 @@
//! Module for parsing ISO Base Media Format aka video/mp4 streams.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
#[cfg(feature = "fuzz")]
extern crate afl;
+#[macro_use]
+extern crate log;
+
extern crate byteorder;
extern crate bitreader;
extern crate num_traits;
use byteorder::{ReadBytesExt, WriteBytesExt};
use bitreader::{BitReader, ReadInto};
use std::io::{Read, Take};
use std::io::Cursor;
use std::cmp;
@@ -31,35 +34,16 @@ mod tests;
// Arbitrary buffer size limit used for raw read_bufs on a box.
const BUF_SIZE_LIMIT: usize = 1024 * 1024;
// Max table length. Calculating in worth case for one week long video, one
// frame per table entry in 30 fps.
const TABLE_SIZE_LIMIT: u32 = 30 * 60 * 60 * 24 * 7;
-static DEBUG_MODE: std::sync::atomic::AtomicBool = std::sync::atomic::ATOMIC_BOOL_INIT;
-
-pub fn set_debug_mode(mode: bool) {
- DEBUG_MODE.store(mode, std::sync::atomic::Ordering::SeqCst);
-}
-
-#[inline(always)]
-fn get_debug_mode() -> bool {
- DEBUG_MODE.load(std::sync::atomic::Ordering::Relaxed)
-}
-
-macro_rules! log {
- ($($args:tt)*) => (
- if get_debug_mode() {
- println!( $( $args )* );
- }
- )
-}
-
// TODO: vec_push() and vec_reserve() needs to be replaced when Rust supports
// fallible memory allocation in raw_vec.
#[allow(unreachable_code)]
pub fn vec_push<T>(vec: &mut Vec<T>, val: T) -> std::result::Result<(), ()> {
#[cfg(feature = "mp4parse_fallible")]
{
return vec.try_push(val);
}
@@ -311,16 +295,17 @@ pub struct ES_Descriptor {
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone)]
pub enum AudioCodecSpecific {
ES_Descriptor(ES_Descriptor),
FLACSpecificBox(FLACSpecificBox),
OpusSpecificBox(OpusSpecificBox),
+ ALACSpecificBox(ALACSpecificBox),
MP3,
LPCM,
}
#[derive(Debug, Clone)]
pub struct AudioSampleEntry {
data_reference_index: u16,
pub channelcount: u32,
@@ -387,16 +372,23 @@ pub struct OpusSpecificBox {
output_channel_count: u8,
pre_skip: u16,
input_sample_rate: u32,
output_gain: i16,
channel_mapping_family: u8,
channel_mapping_table: Option<ChannelMappingTable>,
}
+/// Represent an ALACSpecificBox 'alac'
+#[derive(Debug, Clone)]
+pub struct ALACSpecificBox {
+ version: u8,
+ pub data: Vec<u8>,
+}
+
#[derive(Debug)]
pub struct MovieExtendsBox {
pub fragment_duration: Option<MediaScaledTime>,
}
pub type ByteData = Vec<u8>;
#[derive(Debug, Default)]
@@ -459,16 +451,17 @@ pub enum CodecType {
H264, // 14496-10
MP4V, // 14496-2
VP10,
VP9,
VP8,
EncryptedVideo,
EncryptedAudio,
LPCM, // QT
+ ALAC,
}
impl Default for CodecType {
fn default() -> Self { CodecType::Unknown }
}
/// The media's global (mvhd) timescale in units per second.
#[derive(Debug, Copy, Clone, PartialEq)]
@@ -568,17 +561,17 @@ impl<'a, T: Read> BMFFBox<'a, T> {
BoxIter::new(self)
}
}
impl<'a, T: Read> Drop for BMFFBox<'a, T> {
fn drop(&mut self) {
if self.content.limit() > 0 {
let name: FourCC = From::from(self.head.name);
- log!("Dropping {} bytes in '{}'", self.content.limit(), name);
+ debug!("Dropping {} bytes in '{}'", self.content.limit(), name);
}
}
}
/// Read and parse a box header.
///
/// Call this first to determine the type of a particular mp4 box
/// and its length. Used internally for dispatching to specific
@@ -622,38 +615,38 @@ fn read_fullbox_extra<T: ReadBytesExt>(s
(flags_a as u32) << 16 | (flags_b as u32) << 8 | (flags_c as u32)))
}
/// Skip over the entire contents of a box.
fn skip_box_content<T: Read>(src: &mut BMFFBox<T>) -> Result<()> {
// Skip the contents of unknown chunks.
let to_skip = {
let header = src.get_header();
- log!("{:?} (skipped)", header);
+ debug!("{:?} (skipped)", header);
(header.size - header.offset) as usize
};
assert_eq!(to_skip, src.bytes_left());
skip(src, to_skip)
}
/// Skip over the remain data of a box.
fn skip_box_remain<T: Read>(src: &mut BMFFBox<T>) -> Result<()> {
let remain = {
let header = src.get_header();
let len = src.bytes_left();
- log!("remain {} (skipped) in {:?}", len, header);
+ debug!("remain {} (skipped) in {:?}", len, header);
len
};
skip(src, remain)
}
macro_rules! check_parser_state {
( $src:expr ) => {
if $src.limit() > 0 {
- log!("bad parser state: {} content bytes left", $src.limit());
+ debug!("bad parser state: {} content bytes left", $src.limit());
return Err(Error::InvalidData("unread box content or bad parser sync"));
}
}
}
/// Read the contents of a box, including sub boxes.
///
/// Metadata is accumulated in the passed-through `MediaContext` struct,
@@ -679,27 +672,27 @@ pub fn read_mp4<T: Read>(f: &mut T, cont
// qt: pnot
// possibly allow anything where all printable and/or all lowercase printable
// "four printable characters from the ISO 8859-1 character set"
match b.head.name {
BoxType::FileTypeBox => {
let ftyp = read_ftyp(&mut b)?;
found_ftyp = true;
- log!("{:?}", ftyp);
+ debug!("{:?}", ftyp);
}
BoxType::MovieBox => {
read_moov(&mut b, context)?;
found_moov = true;
}
_ => skip_box_content(&mut b)?,
};
check_parser_state!(b.content);
if found_moov {
- log!("found moov {}, could stop pure 'moov' parser now", if found_ftyp {
+ debug!("found moov {}, could stop pure 'moov' parser now", if found_ftyp {
"and ftyp"
} else {
"but no ftyp"
});
}
}
// XXX(kinetik): This isn't perfect, as a "moov" with no contents is
@@ -723,31 +716,31 @@ fn parse_mvhd<T: Read>(f: &mut BMFFBox<T
fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: &mut MediaContext) -> Result<()> {
let mut iter = f.box_iter();
while let Some(mut b) = iter.next_box()? {
match b.head.name {
BoxType::MovieHeaderBox => {
let (mvhd, timescale) = parse_mvhd(&mut b)?;
context.timescale = timescale;
- log!("{:?}", mvhd);
+ debug!("{:?}", mvhd);
}
BoxType::TrackBox => {
let mut track = Track::new(context.tracks.len());
read_trak(&mut b, &mut track)?;
vec_push(&mut context.tracks, track)?;
}
BoxType::MovieExtendsBox => {
let mvex = read_mvex(&mut b)?;
- log!("{:?}", mvex);
+ debug!("{:?}", mvex);
context.mvex = Some(mvex);
}
BoxType::ProtectionSystemSpecificHeaderBox => {
let pssh = read_pssh(&mut b)?;
- log!("{:?}", pssh);
+ debug!("{:?}", pssh);
vec_push(&mut context.psshs, pssh)?;
}
_ => skip_box_content(&mut b)?,
};
check_parser_state!(b.content);
}
Ok(())
}
@@ -820,17 +813,17 @@ fn read_mehd<T: Read>(src: &mut BMFFBox<
fn read_trak<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> {
let mut iter = f.box_iter();
while let Some(mut b) = iter.next_box()? {
match b.head.name {
BoxType::TrackHeaderBox => {
let tkhd = read_tkhd(&mut b)?;
track.track_id = Some(tkhd.track_id);
track.tkhd = Some(tkhd.clone());
- log!("{:?}", tkhd);
+ debug!("{:?}", tkhd);
}
BoxType::EditBox => read_edts(&mut b, track)?,
BoxType::MediaBox => read_mdia(&mut b, track)?,
_ => skip_box_content(&mut b)?,
};
check_parser_state!(b.content);
}
Ok(())
@@ -855,17 +848,17 @@ fn read_edts<T: Read>(f: &mut BMFFBox<T>
idx += 1;
}
track.empty_duration = Some(MediaScaledTime(empty_duration));
if elst.edits[idx].media_time < 0 {
return Err(Error::InvalidData("unexpected negative media time in edit"));
}
track.media_time = Some(TrackScaledTime::<u64>(elst.edits[idx].media_time as u64,
track.id));
- log!("{:?}", elst);
+ debug!("{:?}", elst);
}
_ => skip_box_content(&mut b)?,
};
check_parser_state!(b.content);
}
Ok(())
}
@@ -885,27 +878,27 @@ fn parse_mdhd<T: Read>(f: &mut BMFFBox<T
fn read_mdia<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> {
let mut iter = f.box_iter();
while let Some(mut b) = iter.next_box()? {
match b.head.name {
BoxType::MediaHeaderBox => {
let (mdhd, duration, timescale) = parse_mdhd(&mut b, track)?;
track.duration = duration;
track.timescale = timescale;
- log!("{:?}", mdhd);
+ debug!("{:?}", mdhd);
}
BoxType::HandlerBox => {
let hdlr = read_hdlr(&mut b)?;
match hdlr.handler_type.value.as_ref() {
"vide" => track.track_type = TrackType::Video,
"soun" => track.track_type = TrackType::Audio,
_ => (),
}
- log!("{:?}", hdlr);
+ debug!("{:?}", hdlr);
}
BoxType::MediaInformationBox => read_minf(&mut b, track)?,
_ => skip_box_content(&mut b)?,
};
check_parser_state!(b.content);
}
Ok(())
}
@@ -923,51 +916,51 @@ fn read_minf<T: Read>(f: &mut BMFFBox<T>
}
fn read_stbl<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> {
let mut iter = f.box_iter();
while let Some(mut b) = iter.next_box()? {
match b.head.name {
BoxType::SampleDescriptionBox => {
let stsd = read_stsd(&mut b, track)?;
- log!("{:?}", stsd);
+ debug!("{:?}", stsd);
}
BoxType::TimeToSampleBox => {
let stts = read_stts(&mut b)?;
- log!("{:?}", stts);
+ debug!("{:?}", stts);
track.stts = Some(stts);
}
BoxType::SampleToChunkBox => {
let stsc = read_stsc(&mut b)?;
- log!("{:?}", stsc);
+ debug!("{:?}", stsc);
track.stsc = Some(stsc);
}
BoxType::SampleSizeBox => {
let stsz = read_stsz(&mut b)?;
- log!("{:?}", stsz);
+ debug!("{:?}", stsz);
track.stsz = Some(stsz);
}
BoxType::ChunkOffsetBox => {
let stco = read_stco(&mut b)?;
- log!("{:?}", stco);
+ debug!("{:?}", stco);
track.stco = Some(stco);
}
BoxType::ChunkLargeOffsetBox => {
let co64 = read_co64(&mut b)?;
- log!("{:?}", co64);
+ debug!("{:?}", co64);
track.stco = Some(co64);
}
BoxType::SyncSampleBox => {
let stss = read_stss(&mut b)?;
- log!("{:?}", stss);
+ debug!("{:?}", stss);
track.stss = Some(stss);
}
BoxType::CompositionOffsetBox => {
let ctts = read_ctts(&mut b)?;
- log!("{:?}", ctts);
+ debug!("{:?}", ctts);
track.ctts = Some(ctts);
}
_ => skip_box_content(&mut b)?,
};
check_parser_state!(b.content);
}
Ok(())
}
@@ -1404,17 +1397,17 @@ fn find_descriptor(data: &[u8], esds: &m
},
DECODER_CONFIG_TAG => {
read_dc_descriptor(descriptor, esds)?;
},
DECODER_SPECIFIC_TAG => {
read_ds_descriptor(descriptor, esds)?;
},
_ => {
- log!("Unsupported descriptor, tag {}", tag);
+ debug!("Unsupported descriptor, tag {}", tag);
},
}
remains = &remains[end as usize .. remains.len()];
}
Ok(())
}
@@ -1457,17 +1450,17 @@ fn read_ds_descriptor(data: &[u8], esds:
if depend_on_core_order > 0 {
bit_reader.skip(14)?; // codeCoderDelay
}
bit_reader.skip(1)?; // extensionFlag
// When channel_counts is 0, we need to parse the program_config_element
// to calculate the channel counts.
if channel_counts == 0 {
- log!("Parsing program_config_element for channel counts");
+ debug!("Parsing program_config_element for channel counts");
bit_reader.skip(4)?; // element_instance_tag
bit_reader.skip(2)?; // object_type
bit_reader.skip(4)?; // sampling_frequency_index
let num_front_channel: u8 = ReadInto::read(bit_reader, 4)?;
let num_side_channel: u8 = ReadInto::read(bit_reader, 4)?;
let num_back_channel:u8 = ReadInto::read(bit_reader, 4)?;
let num_lfe_channel: u8 = ReadInto::read(bit_reader, 2)?;
@@ -1684,16 +1677,38 @@ pub fn serialize_opus_header<W: byteorde
}
}
}
}
};
Ok(())
}
+/// Parse `ALACSpecificBox`.
+fn read_alac<T: Read>(src: &mut BMFFBox<T>) -> Result<ALACSpecificBox> {
+ let (version, flags) = read_fullbox_extra(src)?;
+ if version != 0 {
+ return Err(Error::Unsupported("unknown alac (ALAC) version"));
+ }
+ if flags != 0 {
+ return Err(Error::InvalidData("no-zero alac (ALAC) flags"));
+ }
+
+ let length = src.bytes_left();
+ if length != 24 && length != 48 {
+ return Err(Error::InvalidData("ALACSpecificBox magic cookie is the wrong size"));
+ }
+ let data = read_buf(src, length)?;
+
+ Ok(ALACSpecificBox {
+ version: version,
+ data: data,
+ })
+}
+
/// Parse a hdlr box.
fn read_hdlr<T: Read>(src: &mut BMFFBox<T>) -> Result<HandlerBox> {
let (_, _) = read_fullbox_extra(src)?;
// Skip uninteresting fields.
skip(src, 4)?;
let handler_type = FourCC::from(be_u32(src)?);
@@ -1714,17 +1729,17 @@ fn read_video_sample_entry<T: Read>(src:
let name = src.get_header().name;
let codec_type = match name {
BoxType::AVCSampleEntry | BoxType::AVC3SampleEntry => CodecType::H264,
BoxType::MP4VideoSampleEntry => CodecType::MP4V,
BoxType::VP8SampleEntry => CodecType::VP8,
BoxType::VP9SampleEntry => CodecType::VP9,
BoxType::ProtectedVisualSampleEntry => CodecType::EncryptedVideo,
_ => {
- log!("Unsupported video codec, box {:?} found", name);
+ debug!("Unsupported video codec, box {:?} found", name);
CodecType::Unknown
}
};
// Skip uninteresting fields.
skip(src, 6)?;
let data_reference_index = be_u16(src)?;
@@ -1748,17 +1763,17 @@ fn read_video_sample_entry<T: Read>(src:
if (name != BoxType::AVCSampleEntry &&
name != BoxType::AVC3SampleEntry &&
name != BoxType::ProtectedVisualSampleEntry) ||
codec_specific.is_some() {
return Err(Error::InvalidData("malformed video sample entry"));
}
let avcc_size = b.head.size - b.head.offset;
let avcc = read_buf(&mut b.content, avcc_size as usize)?;
- log!("{:?} (avcc)", avcc);
+ debug!("{:?} (avcc)", avcc);
// TODO(kinetik): Parse avcC box? For now we just stash the data.
codec_specific = Some(VideoCodecSpecific::AVCConfig(avcc));
}
BoxType::VPCodecConfigurationBox => { // vpcC
if (name != BoxType::VP8SampleEntry &&
name != BoxType::VP9SampleEntry &&
name != BoxType::ProtectedVisualSampleEntry) ||
codec_specific.is_some() {
@@ -1776,21 +1791,21 @@ fn read_video_sample_entry<T: Read>(src:
let esds = read_buf(&mut b.content, esds_size as usize)?;
codec_specific = Some(VideoCodecSpecific::ESDSConfig(esds));
}
BoxType::ProtectionSchemeInformationBox => {
if name != BoxType::ProtectedVisualSampleEntry {
return Err(Error::InvalidData("malformed video sample entry"));
}
let sinf = read_sinf(&mut b)?;
- log!("{:?} (sinf)", sinf);
+ debug!("{:?} (sinf)", sinf);
vec_push(&mut protection_info, sinf)?;
}
_ => {
- log!("Unsupported video codec, box {:?} found", b.head.name);
+ debug!("Unsupported video codec, box {:?} found", b.head.name);
skip_box_content(&mut b)?;
}
}
check_parser_state!(b.content);
}
Ok(codec_specific.map_or((CodecType::Unknown, SampleEntry::Unknown),
|codec_specific| (codec_type, SampleEntry::Video(VideoSampleEntry {
@@ -1895,32 +1910,41 @@ fn read_audio_sample_entry<T: Read>(src:
if name != BoxType::OpusSampleEntry ||
codec_specific.is_some() {
return Err(Error::InvalidData("malformed audio sample entry"));
}
let dops = read_dops(&mut b)?;
codec_type = CodecType::Opus;
codec_specific = Some(AudioCodecSpecific::OpusSpecificBox(dops));
}
+ BoxType::ALACSpecificBox => {
+ if name != BoxType::ALACSpecificBox ||
+ codec_specific.is_some() {
+ return Err(Error::InvalidData("malformed audio sample entry"));
+ }
+ let alac = read_alac(&mut b)?;
+ codec_type = CodecType::ALAC;
+ codec_specific = Some(AudioCodecSpecific::ALACSpecificBox(alac));
+ }
BoxType::QTWaveAtom => {
let qt_esds = read_qt_wave_atom(&mut b)?;
codec_type = qt_esds.audio_codec;
codec_specific = Some(AudioCodecSpecific::ES_Descriptor(qt_esds));
}
BoxType::ProtectionSchemeInformationBox => {
if name != BoxType::ProtectedAudioSampleEntry {
return Err(Error::InvalidData("malformed audio sample entry"));
}
let sinf = read_sinf(&mut b)?;
- log!("{:?} (sinf)", sinf);
+ debug!("{:?} (sinf)", sinf);
codec_type = CodecType::EncryptedAudio;
vec_push(&mut protection_info, sinf)?;
}
_ => {
- log!("Unsupported audio codec, box {:?} found", b.head.name);
+ debug!("Unsupported audio codec, box {:?} found", b.head.name);
skip_box_content(&mut b)?;
}
}
check_parser_state!(b.content);
}
Ok(codec_specific.map_or((CodecType::Unknown, SampleEntry::Unknown),
|codec_specific| (codec_type, SampleEntry::Audio(AudioSampleEntry {
@@ -1963,17 +1987,17 @@ fn read_stsd<T: Read>(src: &mut BMFFBox<
skip(&mut b, to_skip)?;
SampleEntry::Unknown
}
Err(e) => return Err(e),
};
if track.data.is_none() {
track.data = Some(description.clone());
} else {
- log!("** don't know how to handle multiple descriptions **");
+ debug!("** don't know how to handle multiple descriptions **");
}
vec_push(&mut descriptions, description)?;
check_parser_state!(b.content);
if descriptions.len() == description_count as usize {
break;
}
}
}
--- a/media/mp4parse-rust/mp4parse/src/tests.rs
+++ b/media/mp4parse-rust/mp4parse/src/tests.rs
@@ -649,16 +649,38 @@ fn serialize_opus_header() {
0x01, 0x06, 0x98, 0x00,
0x80, 0xbb, 0x00, 0x00,
0x00, 0x00, 0x01, 0x04, 0x02,
0x00, 0x04, 0x01, 0x02, 0x03, 0x05,
]);
}
#[test]
+fn read_alac() {
+ let mut stream = make_box(BoxSize::Auto, b"alac", |s| {
+ s.append_repeated(0, 6) // reserved
+ .B16(1) // data reference index
+ .B32(0) // reserved
+ .B32(0) // reserved
+ .B16(2) // channel count
+ .B16(16) // bits per sample
+ .B16(0) // pre_defined
+ .B16(0) // reserved
+ .B32(44100 << 16) // Sample rate
+ .append_bytes(&make_fullbox(BoxSize::Auto, b"alac", 0, |s| {
+ s.append_bytes(&vec![0xfa; 24])
+ }).into_inner())
+ });
+ let mut iter = super::BoxIter::new(&mut stream);
+ let mut stream = iter.next_box().unwrap().unwrap();
+ let r = super::read_audio_sample_entry(&mut stream);
+ assert!(r.is_ok());
+}
+
+#[test]
fn avcc_limit() {
let mut stream = make_box(BoxSize::Auto, b"avc1", |s| {
s.append_repeated(0, 6)
.B16(1)
.append_repeated(0, 16)
.B16(320)
.B16(240)
.append_repeated(0, 14)
--- a/media/mp4parse-rust/mp4parse/tests/public.rs
+++ b/media/mp4parse-rust/mp4parse/tests/public.rs
@@ -91,16 +91,20 @@ fn public_api() {
assert_eq!(flac.blocks[0].data.len(), 34);
"FLAC"
}
mp4::AudioCodecSpecific::OpusSpecificBox(opus) => {
// We don't enter in here, we just check if fields are public.
assert!(opus.version > 0);
"Opus"
}
+ mp4::AudioCodecSpecific::ALACSpecificBox(alac) => {
+ assert!(alac.data.len() == 24 || alac.data.len() == 48);
+ "ALAC"
+ }
mp4::AudioCodecSpecific::MP3 => {
"MP3"
}
mp4::AudioCodecSpecific::LPCM => {
"LPCM"
}
}, "ES");
assert!(a.samplesize > 0);
--- a/media/mp4parse-rust/mp4parse_capi/Cargo.toml
+++ b/media/mp4parse-rust/mp4parse_capi/Cargo.toml
@@ -1,11 +1,11 @@
[package]
name = "mp4parse_capi"
-version = "0.9.1"
+version = "0.10.0"
authors = [
"Ralph Giles <giles@mozilla.com>",
"Matthew Gregan <kinetik@flim.org>",
"Alfredo Yang <ayang@mozilla.com>",
]
description = "Parser for ISO base media file format (mp4)"
documentation = "https://docs.rs/mp4parse_capi/"
@@ -13,19 +13,18 @@ license = "MPL-2.0"
repository = "https://github.com/mozilla/mp4parse-rust"
# Avoid complaints about trying to package test files.
exclude = [
"*.mp4",
]
-[badges]
-travis-ci = { repository = "https://github.com/mozilla/mp4parse-rust" }
+build = false
[dependencies]
-byteorder = "1.0.0"
+byteorder = "1.2.1"
+log = "0.4"
# To enable fallible memory allocation, add 'features = ["mp4parse_fallible"]'
# in mp4parse brace.
-mp4parse = {version = "0.9.1", path = "../mp4parse", features = ["mp4parse_fallible"]}
-num-traits = "0.1.37"
-
+mp4parse = {version = "0.10.0", path = "../mp4parse", features = ["mp4parse_fallible"]}
+num-traits = "0.2.0"
--- a/media/mp4parse-rust/mp4parse_capi/src/lib.rs
+++ b/media/mp4parse-rust/mp4parse_capi/src/lib.rs
@@ -93,16 +93,17 @@ pub enum Mp4parseCodec {
Opus,
Avc,
Vp9,
Mp3,
Mp4v,
Jpeg, // for QT JPEG atom in video track
Ac3,
Ec3,
+ Alac,
}
impl Default for Mp4parseCodec {
fn default() -> Self { Mp4parseCodec::Unknown }
}
#[repr(C)]
#[derive(Default, Debug)]
@@ -292,22 +293,16 @@ pub unsafe extern fn mp4parse_new(io: *c
/// Free an `Mp4parseParser*` allocated by `mp4parse_new()`.
#[no_mangle]
pub unsafe extern fn mp4parse_free(parser: *mut Mp4parseParser) {
assert!(!parser.is_null());
let _ = Box::from_raw(parser);
}
-/// Enable `mp4_parser` log.
-#[no_mangle]
-pub unsafe extern fn mp4parse_log(enable: bool) {
- mp4parse::set_debug_mode(enable);
-}
-
/// Run the `Mp4parseParser*` allocated by `mp4parse_new()` until EOF or error.
#[no_mangle]
pub unsafe extern fn mp4parse_read(parser: *mut Mp4parseParser) -> Mp4parseStatus {
// Validate arguments from C.
if parser.is_null() || (*parser).poisoned() {
return Mp4parseStatus::BadArg;
}
@@ -424,16 +419,18 @@ pub unsafe extern fn mp4parse_get_track_
AudioCodecSpecific::ES_Descriptor(ref esds) if esds.audio_codec == CodecType::AAC =>
Mp4parseCodec::Aac,
AudioCodecSpecific::ES_Descriptor(ref esds) if esds.audio_codec == CodecType::MP3 =>
Mp4parseCodec::Mp3,
AudioCodecSpecific::ES_Descriptor(_) | AudioCodecSpecific::LPCM =>
Mp4parseCodec::Unknown,
AudioCodecSpecific::MP3 =>
Mp4parseCodec::Mp3,
+ AudioCodecSpecific::ALACSpecificBox(_) =>
+ Mp4parseCodec::Alac,
},
Some(SampleEntry::Video(ref video)) => match video.codec_specific {
VideoCodecSpecific::VPxConfig(_) =>
Mp4parseCodec::Vp9,
VideoCodecSpecific::AVCConfig(_) =>
Mp4parseCodec::Avc,
VideoCodecSpecific::ESDSConfig(_) => // MP4V (14496-2) video is unsupported.
Mp4parseCodec::Unknown,
@@ -560,16 +557,20 @@ pub unsafe extern fn mp4parse_get_track_
return Mp4parseStatus::Invalid;
}
(*info).extra_data.length = v.len() as u32;
(*info).extra_data.data = v.as_ptr();
}
}
}
}
+ AudioCodecSpecific::ALACSpecificBox(ref alac) => {
+ (*info).extra_data.length = alac.data.len() as u32;
+ (*info).extra_data.data = alac.data.as_ptr();
+ }
AudioCodecSpecific::MP3 | AudioCodecSpecific::LPCM => (),
}
if let Some(p) = audio.protection_info.iter().find(|sinf| sinf.tenc.is_some()) {
if let Some(ref tenc) = p.tenc {
(*info).protected_data.is_encrypted = tenc.is_encrypted;
(*info).protected_data.iv_size = tenc.iv_size;
(*info).protected_data.kid.set_data(&(tenc.kid));
@@ -1137,24 +1138,16 @@ fn new_parser() {
unsafe {
let parser = mp4parse_new(&io);
assert!(!parser.is_null());
mp4parse_free(parser);
}
}
#[test]
-#[should_panic(expected = "assertion failed")]
-fn free_null_parser() {
- unsafe {
- mp4parse_free(std::ptr::null_mut());
- }
-}
-
-#[test]
fn get_track_count_null_parser() {
unsafe {
let mut count: u32 = 0;
let rv = mp4parse_get_track_count(std::ptr::null(), std::ptr::null_mut());
assert_eq!(rv, Mp4parseStatus::BadArg);
let rv = mp4parse_get_track_count(std::ptr::null(), &mut count);
assert_eq!(rv, Mp4parseStatus::BadArg);
}
--- a/toolkit/library/gtest/rust/Cargo.lock
+++ b/toolkit/library/gtest/rust/Cargo.lock
@@ -595,17 +595,17 @@ dependencies = [
"cubeb 0.3.2",
"cubeb-backend 0.2.0",
"cubeb-core 0.1.0",
"cubeb-pulse 0.0.2",
"encoding_c 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"encoding_glue 0.1.0",
"geckoservo 0.0.1",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "mp4parse_capi 0.9.1",
+ "mp4parse_capi 0.10.0",
"netwerk_helper 0.0.1",
"nserror 0.1.0",
"nsstring 0.1.0",
"prefs_parser 0.0.1",
"rust_url_capi 0.0.1",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
"u2fhid 0.1.0",
"webrender_bindings 0.1.0",
@@ -847,35 +847,37 @@ dependencies = [
[[package]]
name = "moz_cbor"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "mp4parse"
-version = "0.9.1"
+version = "0.10.0"
dependencies = [
"bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"mp4parse_fallible 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mp4parse-gtest"
version = "0.1.0"
[[package]]
name = "mp4parse_capi"
-version = "0.9.1"
+version = "0.10.0"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "mp4parse 0.9.1",
- "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mp4parse 0.10.0",
+ "num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mp4parse_fallible"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -938,16 +940,21 @@ dependencies = [
]
[[package]]
name = "num-traits"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "num-traits"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "num_cpus"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1767,16 +1774,17 @@ dependencies = [
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum moz_cbor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20c82a57087fd5990d7122dbff1607c3b20c3d2958e9d9ad9765aab415e2c91c"
"checksum mp4parse_fallible 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6626c2aef76eb8f984eef02e475883d3fe9112e114720446c5810fc5f045cd30"
"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
"checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
+"checksum num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7de20f146db9d920c45ee8ed8f71681fd9ade71909b48c3acbd766aa504cf10"
"checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
"checksum ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da12c96037889ae0be29dd2bdd260e5a62a7df24e6466d5a15bb8131c1c200a8"
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
"checksum parking_lot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "37f364e2ce5efa24c7d0b6646d5bb61145551a0112f107ffd7499f1a3e322fbd"
"checksum parking_lot_core 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6c677d78851950b3aec390e681a411f78cc250cba277d4f578758a377f727970"
"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"
--- a/toolkit/library/rust/Cargo.lock
+++ b/toolkit/library/rust/Cargo.lock
@@ -593,17 +593,17 @@ dependencies = [
"cubeb 0.3.2",
"cubeb-backend 0.2.0",
"cubeb-core 0.1.0",
"cubeb-pulse 0.0.2",
"encoding_c 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"encoding_glue 0.1.0",
"geckoservo 0.0.1",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "mp4parse_capi 0.9.1",
+ "mp4parse_capi 0.10.0",
"netwerk_helper 0.0.1",
"nserror 0.1.0",
"nsstring 0.1.0",
"prefs_parser 0.0.1",
"rust_url_capi 0.0.1",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
"u2fhid 0.1.0",
"webrender_bindings 0.1.0",
@@ -845,31 +845,33 @@ dependencies = [
[[package]]
name = "moz_cbor"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "mp4parse"
-version = "0.9.1"
+version = "0.10.0"
dependencies = [
"bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"mp4parse_fallible 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mp4parse_capi"
-version = "0.9.1"
+version = "0.10.0"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "mp4parse 0.9.1",
- "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mp4parse 0.10.0",
+ "num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mp4parse_fallible"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -925,16 +927,21 @@ dependencies = [
]
[[package]]
name = "num-traits"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "num-traits"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "num_cpus"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1769,16 +1776,17 @@ dependencies = [
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum moz_cbor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20c82a57087fd5990d7122dbff1607c3b20c3d2958e9d9ad9765aab415e2c91c"
"checksum mp4parse_fallible 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6626c2aef76eb8f984eef02e475883d3fe9112e114720446c5810fc5f045cd30"
"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
"checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
+"checksum num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7de20f146db9d920c45ee8ed8f71681fd9ade71909b48c3acbd766aa504cf10"
"checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
"checksum ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da12c96037889ae0be29dd2bdd260e5a62a7df24e6466d5a15bb8131c1c200a8"
"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
"checksum parking_lot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "37f364e2ce5efa24c7d0b6646d5bb61145551a0112f107ffd7499f1a3e322fbd"
"checksum parking_lot_core 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6c677d78851950b3aec390e681a411f78cc250cba277d4f578758a377f727970"
"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc"