Skip to content

Commit 3755fbf

Browse files
committed
MP4: Fix integer shrinking
This feature wasn't finished, unsure how it wasn't caught sooner. In its current state it'll panic on most numbers. Guess we just got lucky.
1 parent e622a67 commit 3755fbf

File tree

1 file changed

+77
-9
lines changed

1 file changed

+77
-9
lines changed

src/mp4/ilst/write.rs

Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -395,25 +395,34 @@ where
395395
}
396396

397397
fn write_signed_int(int: i32, writer: &mut Cursor<Vec<u8>>) -> Result<()> {
398-
let start_pos = int.trailing_zeros() as usize;
399-
write_int(21, int.to_be_bytes(), start_pos, writer)
398+
write_int(21, int.to_be_bytes(), 4, writer)
399+
}
400+
401+
fn bytes_to_occupy_uint(uint: u32) -> usize {
402+
if uint == 0 {
403+
return 1;
404+
}
405+
406+
let ret = 4 - (uint.to_le().leading_zeros() >> 3) as usize;
407+
if ret == 3 {
408+
return 4;
409+
}
410+
ret
400411
}
401412

402413
fn write_unsigned_int(uint: u32, writer: &mut Cursor<Vec<u8>>) -> Result<()> {
403-
let start_pos = uint.trailing_zeros() as usize;
404-
write_int(22, uint.to_be_bytes(), start_pos, writer)
414+
let bytes_needed = bytes_to_occupy_uint(uint);
415+
write_int(22, uint.to_be_bytes(), bytes_needed, writer)
405416
}
406417

407418
fn write_int(
408419
flags: u32,
409420
bytes: [u8; 4],
410-
mut start_pos: usize,
421+
bytes_needed: usize,
411422
writer: &mut Cursor<Vec<u8>>,
412423
) -> Result<()> {
413-
if start_pos == 1 || start_pos == 4 {
414-
start_pos = 0;
415-
}
416-
write_data(flags, &bytes[start_pos..], writer)
424+
debug_assert!(bytes_needed != 0);
425+
write_data(flags, &bytes[4 - bytes_needed..], writer)
417426
}
418427

419428
fn write_picture(picture: &Picture, writer: &mut Cursor<Vec<u8>>) -> Result<()> {
@@ -459,3 +468,62 @@ fn write_data(flags: u32, data: &[u8], writer: &mut Cursor<Vec<u8>>) -> Result<(
459468

460469
Ok(())
461470
}
471+
472+
#[cfg(test)]
473+
mod tests {
474+
use crate::mp4::ilst::write::bytes_to_occupy_uint;
475+
476+
macro_rules! int_test {
477+
(
478+
func: $fun:expr,
479+
$(
480+
{
481+
input: $input:expr,
482+
expected: $expected:expr $(,)?
483+
}
484+
),+ $(,)?
485+
) => {
486+
$(
487+
{
488+
let bytes = $fun($input);
489+
assert_eq!(&$input.to_be_bytes()[4 - bytes..], &$expected[..]);
490+
}
491+
)+
492+
}
493+
}
494+
495+
#[test]
496+
fn integer_shrinking_unsigned() {
497+
int_test! {
498+
func: bytes_to_occupy_uint,
499+
{
500+
input: 0u32,
501+
expected: [0],
502+
},
503+
{
504+
input: 1u32,
505+
expected: [1],
506+
},
507+
{
508+
input: 32767u32,
509+
expected: [127, 255],
510+
},
511+
{
512+
input: 65535u32,
513+
expected: [255, 255],
514+
},
515+
{
516+
input: 8_388_607_u32,
517+
expected: [0, 127, 255, 255],
518+
},
519+
{
520+
input: 16_777_215_u32,
521+
expected: [0, 255, 255, 255],
522+
},
523+
{
524+
input: u32::MAX,
525+
expected: [255, 255, 255, 255],
526+
},
527+
}
528+
}
529+
}

0 commit comments

Comments
 (0)