Skip to content

Commit 888ce90

Browse files
padenotkinetiknz
authored andcommitted
Expose time in ticks relative to a timebase and not in microseconds
1 parent 4f70fc9 commit 888ce90

File tree

6 files changed

+83
-107
lines changed

6 files changed

+83
-107
lines changed

mp4parse/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mp4parse"
3-
version = "0.16.0"
3+
version = "0.17.0"
44
authors = [
55
"Ralph Giles <[email protected]>",
66
"Matthew Gregan <[email protected]>",

mp4parse/src/unstable.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,14 @@ pub struct Indice {
115115
/// sample. Typically this will be the `start_offset` of the next sample
116116
/// in the file.
117117
pub end_offset: CheckedInteger<u64>,
118-
/// The time in microseconds when the indexed sample should be displayed.
118+
/// The time in ticks when the indexed sample should be displayed.
119119
/// Analogous to the concept of presentation time stamp (pts).
120120
pub start_composition: CheckedInteger<i64>,
121-
/// The time in microseconds when the indexed sample should stop being
121+
/// The time in ticks when the indexed sample should stop being
122122
/// displayed. Typically this would be the `start_composition` time of the
123123
/// next sample if samples were ordered by composition time.
124124
pub end_composition: CheckedInteger<i64>,
125-
/// The time in microseconds that the indexed sample should be decoded at.
125+
/// The time in ticks that the indexed sample should be decoded at.
126126
/// Analogous to the concept of decode time stamp (dts).
127127
pub start_decode: CheckedInteger<i64>,
128128
/// Set if the indexed sample is a sync sample. The meaning of sync is
@@ -140,11 +140,6 @@ pub fn create_sample_table(
140140
track: &Track,
141141
track_offset_time: CheckedInteger<i64>,
142142
) -> Option<TryVec<Indice>> {
143-
let timescale = match track.timescale {
144-
Some(ref t) => TrackTimeScale::<i64>(t.0 as i64, t.1),
145-
_ => return None,
146-
};
147-
148143
let (stsc, stco, stsz, stts) = match (&track.stsc, &track.stco, &track.stsz, &track.stts) {
149144
(Some(a), Some(b), Some(c), Some(d)) => (a, b, c, d),
150145
_ => return None,
@@ -238,15 +233,15 @@ pub fn create_sample_table(
238233
// ctts_offset is the current sample offset time.
239234
let ctts_offset = ctts_offset_iter.next_offset_time();
240235

241-
let start_composition = track_time_to_us((decode_time + ctts_offset)?, timescale)?.0;
236+
let start_composition = decode_time + ctts_offset;
242237

243-
let end_composition = track_time_to_us((sum_delta + ctts_offset)?, timescale)?.0;
238+
let end_composition = sum_delta + ctts_offset;
244239

245-
let start_decode = track_time_to_us(decode_time, timescale)?.0;
240+
let start_decode = decode_time;
246241

247-
sample.start_composition = (track_offset_time + start_composition)?;
248-
sample.end_composition = (track_offset_time + end_composition)?;
249-
sample.start_decode = start_decode.into();
242+
sample.start_composition = CheckedInteger(track_offset_time.0 + start_composition?.0);
243+
sample.end_composition = CheckedInteger(track_offset_time.0 + end_composition?.0);
244+
sample.start_decode = CheckedInteger(start_decode.0);
250245
}
251246

252247
// Correct composition end time due to 'ctts' causes composition time re-ordering.

mp4parse_capi/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mp4parse_capi"
3-
version = "0.16.0"
3+
version = "0.17.0"
44
authors = [
55
"Ralph Giles <[email protected]>",
66
"Matthew Gregan <[email protected]>",
@@ -27,7 +27,7 @@ travis-ci = { repository = "https://github.com/mozilla/mp4parse-rust" }
2727
byteorder = "1.2.1"
2828
fallible_collections = { version = "0.4", features = ["std_io"] }
2929
log = "0.4"
30-
mp4parse = { version = "0.16.0", path = "../mp4parse", features = ["unstable-api"] }
30+
mp4parse = { version = "0.17.0", path = "../mp4parse", features = ["unstable-api"] }
3131
num-traits = "0.2.14"
3232

3333
[dev-dependencies]

mp4parse_capi/src/lib.rs

Lines changed: 34 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,7 @@ use std::io::Read;
4242

4343
// Symbols we need from our rust api.
4444
use mp4parse::serialize_opus_header;
45-
use mp4parse::unstable::{
46-
create_sample_table, media_time_to_us, track_time_to_us, CheckedInteger, Indice, Microseconds,
47-
};
45+
use mp4parse::unstable::{create_sample_table, CheckedInteger, Indice};
4846
use mp4parse::AV1ConfigBox;
4947
use mp4parse::AudioCodecSpecific;
5048
use mp4parse::AvifContext;
@@ -127,10 +125,8 @@ pub struct Mp4parseTrackInfo {
127125
pub track_type: Mp4parseTrackType,
128126
pub track_id: u32,
129127
pub duration: u64,
130-
pub media_time: CheckedInteger<i64>, // wants to be u64? understand how elst adjustment works
131-
// TODO(kinetik): include crypto guff
132-
// If this changes to u64, we can get rid of the strange
133-
// impl Sub for CheckedInteger<u64>
128+
pub media_time: CheckedInteger<i64>,
129+
pub time_scale: u32,
134130
}
135131

136132
#[repr(C)]
@@ -278,9 +274,9 @@ impl Default for Mp4parseTrackVideoInfo {
278274
#[repr(C)]
279275
#[derive(Default, Debug)]
280276
pub struct Mp4parseFragmentInfo {
281-
pub fragment_duration: u64,
282-
// TODO:
283-
// info in trex box.
277+
pub fragment_duration: u64, // in ticks
278+
// TODO:
279+
// info in trex box.
284280
}
285281

286282
#[derive(Default)]
@@ -631,46 +627,34 @@ pub unsafe extern "C" fn mp4parse_get_track_info(
631627

632628
let track = &context.tracks[track_index];
633629

634-
if let (Some(track_timescale), Some(context_timescale)) = (track.timescale, context.timescale) {
635-
let media_time: CheckedInteger<_> = match track
630+
if let (Some(timescale), Some(_)) = (track.timescale, context.timescale) {
631+
info.time_scale = timescale.0 as u32;
632+
let media_time: CheckedInteger<u64> = track
636633
.media_time
637-
.map_or(Some(Microseconds(0)), |media_time| {
638-
track_time_to_us(media_time, track_timescale)
639-
}) {
640-
Some(time) => time.0.into(),
641-
None => return Mp4parseStatus::Invalid,
642-
};
643-
let empty_duration: CheckedInteger<_> = match track
634+
.map_or(0.into(), |media_time| media_time.0.into());
635+
636+
let empty_duration: CheckedInteger<u64> = track
644637
.empty_duration
645-
.map_or(Some(Microseconds(0)), |empty_duration| {
646-
media_time_to_us(empty_duration, context_timescale)
647-
}) {
648-
Some(time) => time.0.into(),
649-
None => return Mp4parseStatus::Invalid,
650-
};
638+
.map_or(0.into(), |empty_duration| empty_duration.0.into());
639+
651640
info.media_time = match media_time - empty_duration {
652641
Some(difference) => difference,
653642
None => return Mp4parseStatus::Invalid,
654643
};
655644

656-
if let Some(track_duration) = track.duration {
657-
match track_time_to_us(track_duration, track_timescale) {
658-
Some(duration) => info.duration = duration.0,
659-
None => return Mp4parseStatus::Invalid,
645+
match track.duration {
646+
Some(duration) => info.duration = duration.0,
647+
None => {
648+
// Duration unknown; stagefright returns 0 for this.
649+
info.duration = 0
660650
}
661-
} else {
662-
// Duration unknown; stagefright returns 0 for this.
663-
info.duration = 0
664651
}
665-
} else {
666-
return Mp4parseStatus::Invalid;
667-
}
652+
};
668653

669654
info.track_id = match track.track_id {
670655
Some(track_id) => track_id,
671656
None => return Mp4parseStatus::Invalid,
672657
};
673-
674658
Mp4parseStatus::Ok
675659
}
676660

@@ -1355,20 +1339,15 @@ fn get_indice_table(
13551339
return Ok(());
13561340
}
13571341

1358-
let media_time = match (&track.media_time, &track.timescale) {
1359-
(&Some(t), &Some(s)) => track_time_to_us(t, s)
1360-
.and_then(|v| i64::try_from(v.0).ok())
1361-
.map(Into::into),
1342+
let media_time = match &track.media_time {
1343+
&Some(t) => i64::try_from(t.0).ok().map(Into::into),
13621344
_ => None,
13631345
};
13641346

1365-
let empty_duration: Option<CheckedInteger<_>> =
1366-
match (&track.empty_duration, &context.timescale) {
1367-
(&Some(e), &Some(s)) => media_time_to_us(e, s)
1368-
.and_then(|v| i64::try_from(v.0).ok())
1369-
.map(Into::into),
1370-
_ => None,
1371-
};
1347+
let empty_duration: Option<CheckedInteger<_>> = match &track.empty_duration {
1348+
&Some(e) => i64::try_from(e.0).ok().map(Into::into),
1349+
_ => None,
1350+
};
13721351

13731352
// Find the track start offset time from 'elst'.
13741353
// 'media_time' maps start time onward, 'empty_duration' adds time offset
@@ -1420,12 +1399,12 @@ pub unsafe extern "C" fn mp4parse_get_fragment_info(
14201399
None => return Mp4parseStatus::Invalid,
14211400
};
14221401

1423-
if let (Some(time), Some(scale)) = (duration, context.timescale) {
1424-
info.fragment_duration = match media_time_to_us(time, scale) {
1425-
Some(time_us) => time_us.0,
1426-
None => return Mp4parseStatus::Invalid,
1402+
match duration {
1403+
Some(duration_ticks) => {
1404+
info.fragment_duration = duration_ticks.0;
14271405
}
1428-
}
1406+
None => return Mp4parseStatus::Invalid,
1407+
};
14291408

14301409
Mp4parseStatus::Ok
14311410
}
@@ -1741,16 +1720,16 @@ fn minimal_mp4_get_track_info() {
17411720
});
17421721
assert_eq!(info.track_type, Mp4parseTrackType::Video);
17431722
assert_eq!(info.track_id, 1);
1744-
assert_eq!(info.duration, 40000);
1723+
assert_eq!(info.duration, 512);
17451724
assert_eq!(info.media_time, 0);
17461725

17471726
assert_eq!(Mp4parseStatus::Ok, unsafe {
17481727
mp4parse_get_track_info(parser, 1, &mut info)
17491728
});
17501729
assert_eq!(info.track_type, Mp4parseTrackType::Audio);
17511730
assert_eq!(info.track_id, 2);
1752-
assert_eq!(info.duration, 61333);
1753-
assert_eq!(info.media_time, 21333);
1731+
assert_eq!(info.duration, 2944);
1732+
assert_eq!(info.media_time, 1024);
17541733

17551734
unsafe {
17561735
mp4parse_free(parser);

mp4parse_capi/tests/test_fragment.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ fn parse_fragment() {
3636
assert_eq!(track_info.track_id, 1);
3737
assert_eq!(track_info.duration, 0);
3838
assert_eq!(track_info.media_time, 0);
39+
assert_eq!(track_info.time_scale, 22050);
3940

4041
let mut audio = Default::default();
4142
rv = mp4parse_get_track_audio_info(parser, 0, &mut audio);
@@ -57,7 +58,7 @@ fn parse_fragment() {
5758
let mut fragment_info = Mp4parseFragmentInfo::default();
5859
rv = mp4parse_get_fragment_info(parser, &mut fragment_info);
5960
assert_eq!(rv, Mp4parseStatus::Ok);
60-
assert_eq!(fragment_info.fragment_duration, 10_032_000);
61+
assert_eq!(fragment_info.fragment_duration, 10_032);
6162

6263
mp4parse_free(parser);
6364
}
@@ -89,6 +90,7 @@ fn parse_opus_fragment() {
8990
assert_eq!(track_info.track_id, 1);
9091
assert_eq!(track_info.duration, 0);
9192
assert_eq!(track_info.media_time, 0);
93+
assert_eq!(track_info.time_scale, 48000);
9294

9395
let mut audio = Default::default();
9496
rv = mp4parse_get_track_audio_info(parser, 0, &mut audio);

0 commit comments

Comments
 (0)