Bug 1179885 - Update rust mp4parser to v0.0.9. r=k17e
authorRalph Giles <giles@mozilla.com>
Thu, 02 Jul 2015 11:19:35 -0700
changeset 251242 011c518c9d23e14b94bd8323de1bc52f60196081
parent 251241 63da57eefeeb192ae5a2daa214d0c699e5072eb1
child 251243 420f6d12f471604011e97db229ad94e7a791cca9
push id28991
push usercbook@mozilla.com
push dateFri, 03 Jul 2015 10:08:14 +0000
treeherdermozilla-central@b6a79816ee71 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersk17e
bugs1179885, 1175322
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1179885 - Update rust mp4parser to v0.0.9. r=k17e Source from https://notabug.org/rillian/mp4parse-rust Modified to use byteorder as a local mod instead of an extern crate, per bug 1175322.
media/libstagefright/binding/MP4Metadata.rs
--- a/media/libstagefright/binding/MP4Metadata.rs
+++ b/media/libstagefright/binding/MP4Metadata.rs
@@ -31,28 +31,29 @@ pub struct MovieHeaderBox {
     pub duration: u64,
     // Ignore other fields.
 }
 
 pub struct TrackHeaderBox {
     pub name: u32,
     pub size: u64,
     pub track_id: u32,
+    pub enabled: bool,
     pub duration: u64,
     pub width: u32,
     pub height: u32,
 }
 
 mod byteorder;
 use byteorder::{BigEndian, ReadBytesExt};
-use std::io::{Read, Result, Seek, SeekFrom, Take};
+use std::io::{Read, Seek, SeekFrom, Take};
 use std::io::Cursor;
 
 /// Parse a box out of a data buffer.
-pub fn read_box_header<T: ReadBytesExt>(src: &mut T) -> Result<BoxHeader> {
+pub fn read_box_header<T: ReadBytesExt>(src: &mut T) -> byteorder::Result<BoxHeader> {
     let tmp_size = try!(src.read_u32::<BigEndian>());
     let name = try!(src.read_u32::<BigEndian>());
     let size = match tmp_size {
         1 => try!(src.read_u64::<BigEndian>()),
         _ => tmp_size as u64,
     };
     assert!(size >= 8);
     if tmp_size == 1 {
@@ -90,67 +91,77 @@ pub fn skip_box_content<T: ReadBytesExt 
 }
 
 /// Helper to construct a Take over the contents of a box.
 fn limit<'a, T: Read>(f: &'a mut T, h: &BoxHeader) -> Take<&'a mut T> {
     f.take(h.size - h.offset)
 }
 
 /// Helper to construct a Cursor over the contents of a box.
-fn recurse<T: Read>(f: &mut T, h: &BoxHeader) {
+fn recurse<T: Read>(f: &mut T, h: &BoxHeader) -> byteorder::Result<()> {
+    use std::error::Error;
     println!("{} -- recursing", h);
     // FIXME: I couldn't figure out how to do this without copying.
     // We use Seek on the Read we return in skip_box_content, but
     // that trait isn't implemented for a Take like our limit()
     // returns. Slurping the buffer and wrapping it in a Cursor
     // functions as a work around.
     let buf: Vec<u8> = limit(f, &h)
         .bytes()
         .map(|u| u.unwrap())
         .collect();
     let mut content = Cursor::new(buf);
     loop {
         match read_box(&mut content) {
             Ok(_) => {},
-            Err(e) => {
-                println!("Error '{:?}' reading box", e.kind());
+            Err(byteorder::Error::UnexpectedEOF) => {
+                // byteorder returns EOF at the end of the buffer.
+                // This isn't an error for us, just an signal to
+                // stop recursion.
+                println!("Caught byteorder::Error::UnexpectedEOF");
                 break;
             },
+            Err(byteorder::Error::Io(e)) => {
+                println!("I/O Error '{:?}' reading box: {}",
+                         e.kind(), e.description());
+                return Err(byteorder::Error::Io(e));
+            },
         }
     }
     println!("{} -- end", h);
+    Ok(())
 }
 
 /// Read the contents of a box, including sub boxes.
 /// Right now it just prints the box value rather than
 /// returning anything.
-pub fn read_box<T: Read + Seek>(f: &mut T) -> Result<()> {
+pub fn read_box<T: Read + Seek>(f: &mut T) -> byteorder::Result<()> {
     read_box_header(f).and_then(|h| {
         match &(fourcc_to_string(h.name))[..] {
             "ftyp" => {
                 let mut content = limit(f, &h);
-                let ftyp = read_ftyp(&mut content, &h).unwrap();
+                let ftyp = try!(read_ftyp(&mut content, &h));
                 println!("{}", ftyp);
             },
-            "moov" => recurse(f, &h),
+            "moov" => try!(recurse(f, &h)),
             "mvhd" => {
                 let mut content = limit(f, &h);
-                let mvhd = read_mvhd(&mut content, &h).unwrap();
+                let mvhd = try!(read_mvhd(&mut content, &h));
                 println!("  {}", mvhd);
             },
-            "trak" => recurse(f, &h),
+            "trak" => try!(recurse(f, &h)),
             "tkhd" => {
                 let mut content = limit(f, &h);
-                let tkhd = read_tkhd(&mut content, &h).unwrap();
+                let tkhd = try!(read_tkhd(&mut content, &h));
                 println!("  {}", tkhd);
             },
             _ => {
                 // Skip the contents of unknown chunks.
                 println!("{} (skipped)", h);
-                skip_box_content(f, &h).unwrap();
+                try!(skip_box_content(f, &h).and(Ok(())));
             },
         };
         Ok(()) // and_then needs a Result to return.
     })
 }
 
 /// Entry point for C language callers.
 /// Take a buffer and call read_box() on it.
@@ -166,126 +177,128 @@ pub unsafe extern fn read_box_from_buffe
     }
 
     // Wrap the buffer we've been give in a slice.
     let b = slice::from_raw_parts(buffer, size);
     let mut c = Cursor::new(b);
 
     // Parse in a subthread.
     let task = thread::spawn(move || {
-        read_box(&mut c).unwrap();
+        read_box(&mut c).or_else(|e| { match e {
+            // Catch EOF. We naturally hit it at end-of-input.
+            byteorder::Error::UnexpectedEOF => { Ok(()) },
+            e => { Err(e) },
+        }}).unwrap();
     });
     // Catch any panics.
     task.join().is_ok()
 }
 
 
 /// Parse an ftype box.
 pub fn read_ftyp<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
-  -> Option<FileTypeBox> {
-    let major = src.read_u32::<BigEndian>().unwrap();
-    let minor = src.read_u32::<BigEndian>().unwrap();
+  -> byteorder::Result<FileTypeBox> {
+    let major = try!(src.read_u32::<BigEndian>());
+    let minor = try!(src.read_u32::<BigEndian>());
     let brand_count = (head.size - 8 - 8) /4;
     let mut brands = Vec::new();
     for _ in 0..brand_count {
-        brands.push(src.read_u32::<BigEndian>().unwrap());
+        brands.push( try!(src.read_u32::<BigEndian>()) );
     }
-    Some(FileTypeBox{
+    Ok(FileTypeBox{
         name: head.name,
         size: head.size,
         major_brand: major,
         minor_version: minor,
         compatible_brands: brands,
     })
 }
 
 /// Parse an mvhd box.
 pub fn read_mvhd<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
-  -> Option<MovieHeaderBox> {
+  -> byteorder::Result<MovieHeaderBox> {
     let (version, _) = read_fullbox_extra(src);
     match version {
         1 => {
             // 64 bit creation and modification times.
             let mut skip: Vec<u8> = vec![0; 16];
-            let r = src.read(&mut skip).unwrap();
+            let r = try!(src.read(&mut skip));
             assert!(r == skip.len());
         },
         0 => {
             // 32 bit creation and modification times.
             // 64 bit creation and modification times.
             let mut skip: Vec<u8> = vec![0; 8];
-            let r = src.read(&mut skip).unwrap();
+            let r = try!(src.read(&mut skip));
             assert!(r == skip.len());
         },
         _ => panic!("invalid mhdr version"),
     }
     let timescale = src.read_u32::<BigEndian>().unwrap();
     let duration = match version {
-        1 => src.read_u64::<BigEndian>().unwrap(),
-        0 => src.read_u32::<BigEndian>().unwrap() as u64,
+        1 => try!(src.read_u64::<BigEndian>()),
+        0 => try!(src.read_u32::<BigEndian>()) as u64,
         _ => panic!("invalid mhdr version"),
     };
     // Skip remaining fields.
     let mut skip: Vec<u8> = vec![0; 80];
-    let r = src.read(&mut skip).unwrap();
+    let r = try!(src.read(&mut skip));
     assert!(r == skip.len());
-    Some(MovieHeaderBox {
+    Ok(MovieHeaderBox {
         name: head.name,
         size: head.size,
         timescale: timescale,
         duration: duration,
     })
 }
 
 /// Parse a tkhd box.
 pub fn read_tkhd<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
-  -> Option<TrackHeaderBox> {
+  -> byteorder::Result<TrackHeaderBox> {
     let (version, flags) = read_fullbox_extra(src);
-    if flags & 0x1u32 == 0 || flags & 0x2u32 == 0 {
-        // Track is disabled.
-        return None;
-    }
+    let disabled = flags & 0x1u32 == 0 || flags & 0x2u32 == 0;
     match version {
         1 => {
             // 64 bit creation and modification times.
             let mut skip: Vec<u8> = vec![0; 16];
-            let r = src.read(&mut skip).unwrap();
+            let r = try!(src.read(&mut skip));
             assert!(r == skip.len());
         },
         0 => {
             // 32 bit creation and modification times.
             // 64 bit creation and modification times.
             let mut skip: Vec<u8> = vec![0; 8];
-            let r = src.read(&mut skip).unwrap();
+            let r = try!(src.read(&mut skip));
             assert!(r == skip.len());
         },
         _ => panic!("invalid tkhd version"),
     }
-    let track_id = src.read_u32::<BigEndian>().unwrap();
-    let _reserved = src.read_u32::<BigEndian>().unwrap();
+    let track_id = try!(src.read_u32::<BigEndian>());
+    let _reserved = try!(src.read_u32::<BigEndian>());
     assert!(_reserved == 0);
     let duration = match version {
         1 => {
-            src.read_u64::<BigEndian>().unwrap()
+            try!(src.read_u64::<BigEndian>())
         },
-        0 => src.read_u32::<BigEndian>().unwrap() as u64,
+        0 => try!(src.read_u32::<BigEndian>()) as u64,
         _ => panic!("invalid tkhd version"),
     };
-    let _reserved = src.read_u32::<BigEndian>().unwrap();
-    let _reserved = src.read_u32::<BigEndian>().unwrap();
+    let _reserved = try!(src.read_u32::<BigEndian>());
+    let _reserved = try!(src.read_u32::<BigEndian>());
     // Skip uninterested fields.
     let mut skip: Vec<u8> = vec![0; 44];
-    let r = src.read(&mut skip).unwrap();
+    let r = try!(src.read(&mut skip));
     assert!(r == skip.len());
-    let width = src.read_u32::<BigEndian>().unwrap();
-    let height = src.read_u32::<BigEndian>().unwrap();
-    Some(TrackHeaderBox {
+    let width = try!(src.read_u32::<BigEndian>());
+    let height = try!(src.read_u32::<BigEndian>());
+    Ok(TrackHeaderBox {
         name: head.name,
         size: head.size,
         track_id: track_id,
+        enabled: !disabled,
         duration: duration,
         width: width,
         height: height,
     })
 }
 
 /// Convert the iso box type or other 4-character value to a string.
 fn fourcc_to_string(name: u32) -> String {
@@ -326,19 +339,20 @@ impl fmt::Display for MovieHeaderBox {
 use std::u16;
 impl fmt::Display for TrackHeaderBox {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let name = fourcc_to_string(self.name);
         // Dimensions are 16.16 fixed-point.
         let base = u16::MAX as f64 + 1.0;
         let width = (self.width as f64) / base;
         let height = (self.height as f64) / base;
-        write!(f, "'{}' {} bytes duration {} id {} {}x{}",
+        let disabled = if self.enabled { "" } else { " (disabled)" };
+        write!(f, "'{}' {} bytes duration {} id {} {}x{}{}",
             name, self.size, self.duration, self.track_id,
-            width, height)
+            width, height, disabled)
     }
 }
 
 #[test]
 fn test_read_box_header() {
     use std::io::Cursor;
     use std::io::Write;
     let mut test: Vec<u8> = vec![0, 0, 0, 8];  // minimal box length