зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1349133 - Update mp4 rust parser. r=kinetik
MozReview-Commit-ID: JDKFUsJBpS9 --HG-- extra : rebase_source : 4c7f569dbafb3b34c485cbf0c35177d27579455c
This commit is contained in:
Родитель
66d934bf84
Коммит
33f2386cd8
|
@ -88,6 +88,7 @@ typedef struct mp4parse_track_video_info {
|
|||
uint32_t display_height;
|
||||
uint16_t image_width;
|
||||
uint16_t image_height;
|
||||
uint16_t rotation;
|
||||
mp4parse_byte_data extra_data;
|
||||
mp4parse_sinf_info protected_data;
|
||||
} mp4parse_track_video_info;
|
||||
|
|
|
@ -2,7 +2,7 @@ diff --git a/media/libstagefright/binding/mp4parse/Cargo.toml b/media/libstagefr
|
|||
index ff9422c..814c4c6 100644
|
||||
--- a/media/libstagefright/binding/mp4parse/Cargo.toml
|
||||
+++ b/media/libstagefright/binding/mp4parse/Cargo.toml
|
||||
@@ -18,18 +18,12 @@ exclude = [
|
||||
@@ -18,19 +18,13 @@ exclude = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
|
@ -11,8 +11,10 @@ index ff9422c..814c4c6 100644
|
|||
-afl-plugin = { version = "0.1.1", optional = true }
|
||||
-abort_on_panic = { version = "1.0.0", optional = true }
|
||||
-bitreader = { version = "0.3.0" }
|
||||
-num-traits = "0.1.37"
|
||||
+byteorder = "1.0.0"
|
||||
+bitreader = { version = "0.3.0" }
|
||||
+num-traits = "0.1.37"
|
||||
|
||||
[dev-dependencies]
|
||||
test-assembler = "0.1.2"
|
||||
|
@ -27,7 +29,7 @@ diff --git a/media/libstagefright/binding/mp4parse_capi/Cargo.toml b/media/libst
|
|||
index aeeebc65..5c0836a 100644
|
||||
--- a/media/libstagefright/binding/mp4parse_capi/Cargo.toml
|
||||
+++ b/media/libstagefright/binding/mp4parse_capi/Cargo.toml
|
||||
@@ -18,21 +18,12 @@ exclude = [
|
||||
@@ -18,22 +18,13 @@ exclude = [
|
||||
"*.mp4",
|
||||
]
|
||||
|
||||
|
@ -40,6 +42,7 @@ index aeeebc65..5c0836a 100644
|
|||
[dependencies]
|
||||
byteorder = "1.0.0"
|
||||
mp4parse = {version = "0.7.1", path = "../mp4parse"}
|
||||
num-traits = "0.1.37"
|
||||
|
||||
-[build-dependencies]
|
||||
-rusty-cheddar = "0.3.2"
|
||||
|
|
|
@ -25,6 +25,7 @@ travis-ci = { repository = "https://github.com/mozilla/mp4parse-rust" }
|
|||
[dependencies]
|
||||
byteorder = "1.0.0"
|
||||
bitreader = { version = "0.3.0" }
|
||||
num-traits = "0.1.37"
|
||||
|
||||
[dev-dependencies]
|
||||
test-assembler = "0.1.2"
|
||||
|
|
|
@ -10,11 +10,13 @@ extern crate afl;
|
|||
|
||||
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;
|
||||
use num_traits::Num;
|
||||
|
||||
mod boxes;
|
||||
use boxes::{BoxType, FourCC};
|
||||
|
@ -118,6 +120,19 @@ struct MovieHeaderBox {
|
|||
duration: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Matrix {
|
||||
pub a: i32, // 16.16 fix point
|
||||
pub b: i32, // 16.16 fix point
|
||||
pub u: i32, // 2.30 fix point
|
||||
pub c: i32, // 16.16 fix point
|
||||
pub d: i32, // 16.16 fix point
|
||||
pub v: i32, // 2.30 fix point
|
||||
pub x: i32, // 16.16 fix point
|
||||
pub y: i32, // 16.16 fix point
|
||||
pub w: i32, // 2.30 fix point
|
||||
}
|
||||
|
||||
/// Track header box 'tkhd'
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TrackHeaderBox {
|
||||
|
@ -126,6 +141,7 @@ pub struct TrackHeaderBox {
|
|||
pub duration: u64,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub matrix: Matrix,
|
||||
}
|
||||
|
||||
/// Edit list box 'elst'
|
||||
|
@ -406,12 +422,20 @@ pub struct MediaScaledTime(pub u64);
|
|||
/// The track's local (mdhd) timescale.
|
||||
/// Members are timescale units per second and the track id.
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct TrackTimeScale(pub u64, pub usize);
|
||||
pub struct TrackTimeScale<T: Num>(pub T, pub usize);
|
||||
|
||||
/// A time to be scaled by the track's local (mdhd) timescale.
|
||||
/// Members are time in scale units and the track id.
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct TrackScaledTime(pub u64, pub usize);
|
||||
pub struct TrackScaledTime<T: Num>(pub T, pub usize);
|
||||
|
||||
impl <T> std::ops::Add for TrackScaledTime<T> where T: Num {
|
||||
type Output = TrackScaledTime<T>;
|
||||
|
||||
fn add(self, other: TrackScaledTime<T>) -> TrackScaledTime<T> {
|
||||
TrackScaledTime::<T>(self.0 + other.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
/// A fragmented file contains no sample data in stts, stsc, and stco.
|
||||
#[derive(Debug, Default)]
|
||||
|
@ -431,12 +455,12 @@ impl EmptySampleTableBoxes {
|
|||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Track {
|
||||
id: usize,
|
||||
pub id: usize,
|
||||
pub track_type: TrackType,
|
||||
pub empty_duration: Option<MediaScaledTime>,
|
||||
pub media_time: Option<TrackScaledTime>,
|
||||
pub timescale: Option<TrackTimeScale>,
|
||||
pub duration: Option<TrackScaledTime>,
|
||||
pub media_time: Option<TrackScaledTime<u64>>,
|
||||
pub timescale: Option<TrackTimeScale<u64>>,
|
||||
pub duration: Option<TrackScaledTime<u64>>,
|
||||
pub track_id: Option<u32>,
|
||||
pub codec_type: CodecType,
|
||||
pub empty_sample_boxes: EmptySampleTableBoxes,
|
||||
|
@ -793,7 +817,7 @@ fn read_edts<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> {
|
|||
if elst.edits[idx].media_time < 0 {
|
||||
return Err(Error::InvalidData("unexpected negative media time in edit"));
|
||||
}
|
||||
track.media_time = Some(TrackScaledTime(elst.edits[idx].media_time as u64,
|
||||
track.media_time = Some(TrackScaledTime::<u64>(elst.edits[idx].media_time as u64,
|
||||
track.id));
|
||||
log!("{:?}", elst);
|
||||
}
|
||||
|
@ -804,16 +828,16 @@ fn read_edts<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_mdhd<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<(MediaHeaderBox, Option<TrackScaledTime>, Option<TrackTimeScale>)> {
|
||||
fn parse_mdhd<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<(MediaHeaderBox, Option<TrackScaledTime<u64>>, Option<TrackTimeScale<u64>>)> {
|
||||
let mdhd = read_mdhd(f)?;
|
||||
let duration = match mdhd.duration {
|
||||
std::u64::MAX => None,
|
||||
duration => Some(TrackScaledTime(duration, track.id)),
|
||||
duration => Some(TrackScaledTime::<u64>(duration, track.id)),
|
||||
};
|
||||
if mdhd.timescale == 0 {
|
||||
return Err(Error::InvalidData("zero timescale in mdhd"));
|
||||
}
|
||||
let timescale = Some(TrackTimeScale(mdhd.timescale as u64, track.id));
|
||||
let timescale = Some(TrackTimeScale::<u64>(mdhd.timescale as u64, track.id));
|
||||
Ok((mdhd, duration, timescale))
|
||||
}
|
||||
|
||||
|
@ -989,7 +1013,14 @@ fn read_tkhd<T: Read>(src: &mut BMFFBox<T>) -> Result<TrackHeaderBox> {
|
|||
_ => return Err(Error::InvalidData("unhandled tkhd version")),
|
||||
};
|
||||
// Skip uninteresting fields.
|
||||
skip(src, 52)?;
|
||||
skip(src, 16)?;
|
||||
|
||||
let matrix = Matrix{
|
||||
a: be_i32(src)?, b: be_i32(src)?, u: be_i32(src)?,
|
||||
c: be_i32(src)?, d: be_i32(src)?, v: be_i32(src)?,
|
||||
x: be_i32(src)?, y: be_i32(src)?, w: be_i32(src)?,
|
||||
};
|
||||
|
||||
let width = be_u32(src)?;
|
||||
let height = be_u32(src)?;
|
||||
Ok(TrackHeaderBox {
|
||||
|
@ -998,6 +1029,7 @@ fn read_tkhd<T: Read>(src: &mut BMFFBox<T>) -> Result<TrackHeaderBox> {
|
|||
duration: duration,
|
||||
width: width,
|
||||
height: height,
|
||||
matrix: matrix,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1165,12 +1197,10 @@ fn read_ctts<T: Read>(src: &mut BMFFBox<T>) -> Result<CompositionOffsetBox> {
|
|||
let mut offsets = Vec::new();
|
||||
for _ in 0..counts {
|
||||
let (sample_count, time_offset) = match version {
|
||||
0 => {
|
||||
let count = be_u32(src)?;
|
||||
let offset = TimeOffsetVersion::Version0(be_u32(src)?);
|
||||
(count, offset)
|
||||
},
|
||||
1 => {
|
||||
// According to spec, Version0 shoule be used when version == 0;
|
||||
// however, some buggy contents have negative value when version == 0.
|
||||
// So we always use Version1 here.
|
||||
0...1 => {
|
||||
let count = be_u32(src)?;
|
||||
let offset = TimeOffsetVersion::Version1(be_i32(src)?);
|
||||
(count, offset)
|
||||
|
|
|
@ -23,6 +23,7 @@ build = false
|
|||
[dependencies]
|
||||
byteorder = "1.0.0"
|
||||
mp4parse = {version = "0.7.1", path = "../mp4parse"}
|
||||
num-traits = "0.1.37"
|
||||
|
||||
# Somewhat heavy-handed, but we want at least -Z force-overflow-checks=on.
|
||||
[profile.release]
|
||||
|
|
|
@ -36,10 +36,12 @@
|
|||
|
||||
extern crate mp4parse;
|
||||
extern crate byteorder;
|
||||
extern crate num_traits;
|
||||
|
||||
use std::io::Read;
|
||||
use std::collections::HashMap;
|
||||
use byteorder::WriteBytesExt;
|
||||
use num_traits::{PrimInt, Zero};
|
||||
|
||||
// Symbols we need from our rust api.
|
||||
use mp4parse::MediaContext;
|
||||
|
@ -194,6 +196,7 @@ pub struct mp4parse_track_video_info {
|
|||
pub display_height: u32,
|
||||
pub image_width: u16,
|
||||
pub image_height: u16,
|
||||
pub rotation: u16,
|
||||
pub extra_data: mp4parse_byte_data,
|
||||
pub protected_data: mp4parse_sinf_info,
|
||||
}
|
||||
|
@ -374,28 +377,33 @@ pub unsafe extern fn mp4parse_get_track_count(parser: *const mp4parse_parser, co
|
|||
/// (n * s) / d is split into floor(n / d) * s + (n % d) * s / d.
|
||||
///
|
||||
/// Return None on overflow or if the denominator is zero.
|
||||
fn rational_scale(numerator: u64, denominator: u64, scale: u64) -> Option<u64> {
|
||||
if denominator == 0 {
|
||||
fn rational_scale<T, S>(numerator: T, denominator: T, scale2: S) -> Option<T>
|
||||
where T: PrimInt + Zero, S: PrimInt {
|
||||
if denominator.is_zero() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let integer = numerator / denominator;
|
||||
let remainder = numerator % denominator;
|
||||
match integer.checked_mul(scale) {
|
||||
Some(integer) => remainder.checked_mul(scale)
|
||||
.and_then(|remainder| (remainder/denominator).checked_add(integer)),
|
||||
None => None,
|
||||
}
|
||||
num_traits::cast(scale2).and_then(|s| {
|
||||
match integer.checked_mul(&s) {
|
||||
Some(integer) => remainder.checked_mul(&s)
|
||||
.and_then(|remainder| (remainder/denominator).checked_add(&integer)),
|
||||
None => None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn media_time_to_us(time: MediaScaledTime, scale: MediaTimeScale) -> Option<u64> {
|
||||
let microseconds_per_second = 1000000;
|
||||
rational_scale(time.0, scale.0, microseconds_per_second)
|
||||
rational_scale::<u64, u64>(time.0, scale.0, microseconds_per_second)
|
||||
}
|
||||
|
||||
fn track_time_to_us(time: TrackScaledTime, scale: TrackTimeScale) -> Option<u64> {
|
||||
fn track_time_to_us<T>(time: TrackScaledTime<T>, scale: TrackTimeScale<T>) -> Option<T>
|
||||
where T: PrimInt + Zero {
|
||||
assert_eq!(time.1, scale.1);
|
||||
let microseconds_per_second = 1000000;
|
||||
rational_scale(time.0, scale.0, microseconds_per_second)
|
||||
rational_scale::<T, u64>(time.0, scale.0, microseconds_per_second)
|
||||
}
|
||||
|
||||
/// Fill the supplied `mp4parse_track_info` with metadata for `track`.
|
||||
|
@ -626,6 +634,14 @@ pub unsafe extern fn mp4parse_get_track_video_info(parser: *mut mp4parse_parser,
|
|||
if let Some(ref tkhd) = track.tkhd {
|
||||
(*info).display_width = tkhd.width >> 16; // 16.16 fixed point
|
||||
(*info).display_height = tkhd.height >> 16; // 16.16 fixed point
|
||||
let matrix = (tkhd.matrix.a >> 16, tkhd.matrix.b >> 16,
|
||||
tkhd.matrix.c >> 16, tkhd.matrix.d >> 16);
|
||||
(*info).rotation = match matrix {
|
||||
( 0, 1, -1, 0) => 90, // rotate 90 degrees
|
||||
(-1, 0, 0, -1) => 180, // rotate 180 degrees
|
||||
( 0, -1, 1, 0) => 270, // rotate 270 degrees
|
||||
_ => 0,
|
||||
};
|
||||
} else {
|
||||
return MP4PARSE_ERROR_INVALID;
|
||||
}
|
||||
|
@ -723,6 +739,7 @@ struct TimeOffsetIterator<'a> {
|
|||
cur_sample_range: std::ops::Range<u32>,
|
||||
cur_offset: i64,
|
||||
ctts_iter: Option<std::slice::Iter<'a, mp4parse::TimeOffset>>,
|
||||
track_id: usize,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for TimeOffsetIterator<'a> {
|
||||
|
@ -761,10 +778,10 @@ impl<'a> Iterator for TimeOffsetIterator<'a> {
|
|||
}
|
||||
|
||||
impl<'a> TimeOffsetIterator<'a> {
|
||||
fn next_offset_time(&mut self) -> i64 {
|
||||
fn next_offset_time(&mut self) -> TrackScaledTime<i64> {
|
||||
match self.next() {
|
||||
Some(v) => v as i64,
|
||||
_ => 0,
|
||||
Some(v) => TrackScaledTime::<i64>(v as i64, self.track_id),
|
||||
_ => TrackScaledTime::<i64>(0, self.track_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -775,13 +792,14 @@ impl<'a> TimeOffsetIterator<'a> {
|
|||
//
|
||||
// For example:
|
||||
// (2, 3000), (1, 2999) to (3000, 3000, 2999).
|
||||
struct TimeToSampleIteraor<'a> {
|
||||
struct TimeToSampleIterator<'a> {
|
||||
cur_sample_count: std::ops::Range<u32>,
|
||||
cur_sample_delta: u32,
|
||||
stts_iter: std::slice::Iter<'a, mp4parse::Sample>,
|
||||
track_id: usize,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for TimeToSampleIteraor<'a> {
|
||||
impl<'a> Iterator for TimeToSampleIterator<'a> {
|
||||
type Item = u32;
|
||||
|
||||
fn next(&mut self) -> Option<u32> {
|
||||
|
@ -802,11 +820,11 @@ impl<'a> Iterator for TimeToSampleIteraor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> TimeToSampleIteraor<'a> {
|
||||
fn next_delta(&mut self) -> u32 {
|
||||
impl<'a> TimeToSampleIterator<'a> {
|
||||
fn next_delta(&mut self) -> TrackScaledTime<i64> {
|
||||
match self.next() {
|
||||
Some(v) => v,
|
||||
_ => 0,
|
||||
Some(v) => TrackScaledTime::<i64>(v as i64, self.track_id),
|
||||
_ => TrackScaledTime::<i64>(0, self.track_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -856,33 +874,10 @@ impl<'a> Iterator for SampleToChunkIterator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
// A helper struct to convert track time to us.
|
||||
struct PresentationTime {
|
||||
time: i64,
|
||||
scale: TrackTimeScale
|
||||
}
|
||||
|
||||
impl PresentationTime {
|
||||
fn new(time: i64, scale: TrackTimeScale) -> PresentationTime {
|
||||
PresentationTime {
|
||||
time: time,
|
||||
scale: scale,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_us(&self) -> i64 {
|
||||
let track_time = TrackScaledTime(self.time as u64, self.scale.1);
|
||||
match track_time_to_us(track_time, self.scale) {
|
||||
Some(v) => v as i64,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_sample_table(track: &Track, track_offset_time: i64) -> Option<Vec<mp4parse_indice>> {
|
||||
let timescale = match track.timescale {
|
||||
Some(t) => t,
|
||||
_ => return None,
|
||||
Some(ref t) => TrackTimeScale::<i64>(t.0 as i64, t.1),
|
||||
_ => TrackTimeScale::<i64>(0, 0),
|
||||
};
|
||||
|
||||
let (stsc, stco, stsz, stts) =
|
||||
|
@ -957,12 +952,14 @@ fn create_sample_table(track: &Track, track_offset_time: i64) -> Option<Vec<mp4p
|
|||
cur_sample_range: (0 .. 0),
|
||||
cur_offset: 0,
|
||||
ctts_iter: ctts_iter,
|
||||
track_id: track.id,
|
||||
};
|
||||
|
||||
let mut stts_iter = TimeToSampleIteraor {
|
||||
let mut stts_iter = TimeToSampleIterator {
|
||||
cur_sample_count: (0 .. 0),
|
||||
cur_sample_delta: 0,
|
||||
stts_iter: stts.samples.as_slice().iter(),
|
||||
track_id: track.id,
|
||||
};
|
||||
|
||||
// sum_delta is the sum of stts_iter delta.
|
||||
|
@ -971,20 +968,38 @@ fn create_sample_table(track: &Track, track_offset_time: i64) -> Option<Vec<mp4p
|
|||
// composition time => CT(n) = DT(n) + CTTS(n)
|
||||
// Note:
|
||||
// composition time needs to add the track offset time from 'elst' table.
|
||||
let mut sum_delta = PresentationTime::new(0, timescale);
|
||||
let mut sum_delta = TrackScaledTime::<i64>(0, track.id);
|
||||
for sample in sample_table.as_mut_slice() {
|
||||
let decode_time = sum_delta.to_us();
|
||||
sum_delta.time += stts_iter.next_delta() as i64;
|
||||
let decode_time = sum_delta;
|
||||
sum_delta = sum_delta + stts_iter.next_delta();
|
||||
|
||||
// ctts_offset is the current sample offset time.
|
||||
let ctts_offset = PresentationTime::new(ctts_offset_iter.next_offset_time(), timescale);
|
||||
let ctts_offset = ctts_offset_iter.next_offset_time();
|
||||
|
||||
let start_composition = decode_time + ctts_offset.to_us() + track_offset_time;
|
||||
let end_composition = sum_delta.to_us() + ctts_offset.to_us() + track_offset_time;
|
||||
// ctts_offset could be negative but (decode_time + ctts_offset) should always be positive
|
||||
// value.
|
||||
let start_composition = track_time_to_us(decode_time + ctts_offset, timescale).and_then(|t| {
|
||||
if t < 0 { return None; }
|
||||
Some(t)
|
||||
});
|
||||
|
||||
sample.start_decode = decode_time;
|
||||
sample.start_composition = start_composition;
|
||||
sample.end_composition = end_composition;
|
||||
// ctts_offset could be negative but (sum_delta + ctts_offset) should always be positive
|
||||
// value.
|
||||
let end_composition = track_time_to_us(sum_delta + ctts_offset, timescale).and_then(|t| {
|
||||
if t < 0 { return None; }
|
||||
Some(t)
|
||||
});
|
||||
|
||||
let start_decode = track_time_to_us(decode_time, timescale);
|
||||
|
||||
match (start_composition, end_composition, start_decode) {
|
||||
(Some(s_c), Some(e_c), Some(s_d)) => {
|
||||
sample.start_composition = s_c + track_offset_time;
|
||||
sample.end_composition = e_c + track_offset_time;
|
||||
sample.start_decode = s_d;
|
||||
},
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
|
||||
// Correct composition end time due to 'ctts' causes composition time re-ordering.
|
||||
|
@ -1215,6 +1230,7 @@ fn arg_validation() {
|
|||
display_height: 0,
|
||||
image_width: 0,
|
||||
image_height: 0,
|
||||
rotation: 0,
|
||||
extra_data: mp4parse_byte_data::default(),
|
||||
protected_data: Default::default(),
|
||||
};
|
||||
|
@ -1261,6 +1277,7 @@ fn arg_validation_with_parser() {
|
|||
display_height: 0,
|
||||
image_width: 0,
|
||||
image_height: 0,
|
||||
rotation: 0,
|
||||
extra_data: mp4parse_byte_data::default(),
|
||||
protected_data: Default::default(),
|
||||
};
|
||||
|
@ -1334,6 +1351,7 @@ fn arg_validation_with_data() {
|
|||
display_height: 0,
|
||||
image_width: 0,
|
||||
image_height: 0,
|
||||
rotation: 0,
|
||||
extra_data: mp4parse_byte_data::default(),
|
||||
protected_data: Default::default(),
|
||||
};
|
||||
|
@ -1368,6 +1386,7 @@ fn arg_validation_with_data() {
|
|||
display_height: 0,
|
||||
image_width: 0,
|
||||
image_height: 0,
|
||||
rotation: 0,
|
||||
extra_data: mp4parse_byte_data::default(),
|
||||
protected_data: Default::default(),
|
||||
};
|
||||
|
@ -1389,14 +1408,14 @@ fn arg_validation_with_data() {
|
|||
|
||||
#[test]
|
||||
fn rational_scale_overflow() {
|
||||
assert_eq!(rational_scale(17, 3, 1000), Some(5666));
|
||||
assert_eq!(rational_scale::<u64, u64>(17, 3, 1000), Some(5666));
|
||||
let large = 0x4000_0000_0000_0000;
|
||||
assert_eq!(rational_scale(large, 2, 2), Some(large));
|
||||
assert_eq!(rational_scale(large, 4, 4), Some(large));
|
||||
assert_eq!(rational_scale(large, 2, 8), None);
|
||||
assert_eq!(rational_scale(large, 8, 4), Some(large/2));
|
||||
assert_eq!(rational_scale(large + 1, 4, 4), Some(large+1));
|
||||
assert_eq!(rational_scale(large, 40, 1000), None);
|
||||
assert_eq!(rational_scale::<u64, u64>(large, 2, 2), Some(large));
|
||||
assert_eq!(rational_scale::<u64, u64>(large, 4, 4), Some(large));
|
||||
assert_eq!(rational_scale::<u64, u64>(large, 2, 8), None);
|
||||
assert_eq!(rational_scale::<u64, u64>(large, 8, 4), Some(large/2));
|
||||
assert_eq!(rational_scale::<u64, u64>(large + 1, 4, 4), Some(large+1));
|
||||
assert_eq!(rational_scale::<u64, u64>(large, 40, 1000), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1408,7 +1427,7 @@ fn media_time_overflow() {
|
|||
|
||||
#[test]
|
||||
fn track_time_overflow() {
|
||||
let scale = TrackTimeScale(44100, 0);
|
||||
let duration = TrackScaledTime(4413527634807900, 0);
|
||||
let scale = TrackTimeScale(44100u64, 0);
|
||||
let duration = TrackScaledTime(4413527634807900u64, 0);
|
||||
assert_eq!(track_time_to_us(duration, scale), Some(100079991719000000));
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# Script to update mp4parse-rust sources to latest upstream
|
||||
|
||||
# Default version.
|
||||
VER=6cd06d46565f55a8259d4ad7f083c52d6335750f
|
||||
VER=b78dc3e4e80ce4132e7880ae068d0672cbfeaa48
|
||||
|
||||
# Accept version or commit from the command line.
|
||||
if test -n "$1"; then
|
||||
|
|
|
@ -443,6 +443,7 @@ version = "0.7.1"
|
|||
dependencies = [
|
||||
"bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -455,6 +456,7 @@ version = "0.7.1"
|
|||
dependencies = [
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mp4parse 0.7.1",
|
||||
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -441,6 +441,7 @@ version = "0.7.1"
|
|||
dependencies = [
|
||||
"bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -449,6 +450,7 @@ version = "0.7.1"
|
|||
dependencies = [
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mp4parse 0.7.1",
|
||||
"num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
Загрузка…
Ссылка в новой задаче