mirror of
https://github.com/alfg/mp4-rust.git
synced 2025-01-20 08:38:06 +00:00
Proper handle display matrix (#72)
This commit is contained in:
parent
084381bde5
commit
7218ada431
2 changed files with 114 additions and 34 deletions
|
@ -1,6 +1,6 @@
|
||||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||||
|
use serde::Serialize;
|
||||||
use std::io::{Read, Seek, Write};
|
use std::io::{Read, Seek, Write};
|
||||||
use serde::{Serialize};
|
|
||||||
|
|
||||||
use crate::mp4box::*;
|
use crate::mp4box::*;
|
||||||
|
|
||||||
|
@ -15,6 +15,12 @@ pub struct MvhdBox {
|
||||||
|
|
||||||
#[serde(with = "value_u32")]
|
#[serde(with = "value_u32")]
|
||||||
pub rate: FixedPointU16,
|
pub rate: FixedPointU16,
|
||||||
|
#[serde(with = "value_u8")]
|
||||||
|
pub volume: FixedPointU8,
|
||||||
|
|
||||||
|
pub matrix: tkhd::Matrix,
|
||||||
|
|
||||||
|
pub next_track_id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MvhdBox {
|
impl MvhdBox {
|
||||||
|
@ -44,6 +50,9 @@ impl Default for MvhdBox {
|
||||||
timescale: 1000,
|
timescale: 1000,
|
||||||
duration: 0,
|
duration: 0,
|
||||||
rate: FixedPointU16::new(1),
|
rate: FixedPointU16::new(1),
|
||||||
|
matrix: tkhd::Matrix::default(),
|
||||||
|
volume: FixedPointU8::new(1),
|
||||||
|
next_track_id: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,8 +71,16 @@ impl Mp4Box for MvhdBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn summary(&self) -> Result<String> {
|
fn summary(&self) -> Result<String> {
|
||||||
let s = format!("creation_time={} timescale={} duration={} rate={}",
|
let s = format!(
|
||||||
self.creation_time, self.timescale, self.duration, self.rate.value());
|
"creation_time={} timescale={} duration={} rate={} volume={}, matrix={}, next_track_id={}",
|
||||||
|
self.creation_time,
|
||||||
|
self.timescale,
|
||||||
|
self.duration,
|
||||||
|
self.rate.value(),
|
||||||
|
self.volume.value(),
|
||||||
|
self.matrix,
|
||||||
|
self.next_track_id
|
||||||
|
);
|
||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,6 +110,28 @@ impl<R: Read + Seek> ReadBox<&mut R> for MvhdBox {
|
||||||
};
|
};
|
||||||
let rate = FixedPointU16::new_raw(reader.read_u32::<BigEndian>()?);
|
let rate = FixedPointU16::new_raw(reader.read_u32::<BigEndian>()?);
|
||||||
|
|
||||||
|
let volume = FixedPointU8::new_raw(reader.read_u16::<BigEndian>()?);
|
||||||
|
|
||||||
|
reader.read_u16::<BigEndian>()?; // reserved = 0
|
||||||
|
|
||||||
|
reader.read_u64::<BigEndian>()?; // reserved = 0
|
||||||
|
|
||||||
|
let matrix = tkhd::Matrix {
|
||||||
|
a: reader.read_i32::<BigEndian>()?,
|
||||||
|
b: reader.read_i32::<BigEndian>()?,
|
||||||
|
u: reader.read_i32::<BigEndian>()?,
|
||||||
|
c: reader.read_i32::<BigEndian>()?,
|
||||||
|
d: reader.read_i32::<BigEndian>()?,
|
||||||
|
v: reader.read_i32::<BigEndian>()?,
|
||||||
|
x: reader.read_i32::<BigEndian>()?,
|
||||||
|
y: reader.read_i32::<BigEndian>()?,
|
||||||
|
w: reader.read_i32::<BigEndian>()?,
|
||||||
|
};
|
||||||
|
|
||||||
|
skip_bytes(reader, 24)?; // pre_defined = 0
|
||||||
|
|
||||||
|
let next_track_id = reader.read_u32::<BigEndian>()?;
|
||||||
|
|
||||||
skip_bytes_to(reader, start + size)?;
|
skip_bytes_to(reader, start + size)?;
|
||||||
|
|
||||||
Ok(MvhdBox {
|
Ok(MvhdBox {
|
||||||
|
@ -103,6 +142,9 @@ impl<R: Read + Seek> ReadBox<&mut R> for MvhdBox {
|
||||||
timescale,
|
timescale,
|
||||||
duration,
|
duration,
|
||||||
rate,
|
rate,
|
||||||
|
volume,
|
||||||
|
matrix,
|
||||||
|
next_track_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,8 +171,25 @@ impl<W: Write> WriteBox<&mut W> for MvhdBox {
|
||||||
}
|
}
|
||||||
writer.write_u32::<BigEndian>(self.rate.raw_value())?;
|
writer.write_u32::<BigEndian>(self.rate.raw_value())?;
|
||||||
|
|
||||||
// XXX volume, ...
|
writer.write_u16::<BigEndian>(self.volume.raw_value())?;
|
||||||
write_zeros(writer, 76)?;
|
|
||||||
|
writer.write_u16::<BigEndian>(0)?; // reserved = 0
|
||||||
|
|
||||||
|
writer.write_u64::<BigEndian>(0)?; // reserved = 0
|
||||||
|
|
||||||
|
writer.write_i32::<BigEndian>(self.matrix.a)?;
|
||||||
|
writer.write_i32::<BigEndian>(self.matrix.b)?;
|
||||||
|
writer.write_i32::<BigEndian>(self.matrix.u)?;
|
||||||
|
writer.write_i32::<BigEndian>(self.matrix.c)?;
|
||||||
|
writer.write_i32::<BigEndian>(self.matrix.d)?;
|
||||||
|
writer.write_i32::<BigEndian>(self.matrix.v)?;
|
||||||
|
writer.write_i32::<BigEndian>(self.matrix.x)?;
|
||||||
|
writer.write_i32::<BigEndian>(self.matrix.y)?;
|
||||||
|
writer.write_i32::<BigEndian>(self.matrix.w)?;
|
||||||
|
|
||||||
|
write_zeros(writer, 24)?; // pre_defined = 0
|
||||||
|
|
||||||
|
writer.write_u32::<BigEndian>(self.next_track_id)?;
|
||||||
|
|
||||||
Ok(size)
|
Ok(size)
|
||||||
}
|
}
|
||||||
|
@ -152,6 +211,9 @@ mod tests {
|
||||||
timescale: 1000,
|
timescale: 1000,
|
||||||
duration: 634634,
|
duration: 634634,
|
||||||
rate: FixedPointU16::new(1),
|
rate: FixedPointU16::new(1),
|
||||||
|
volume: FixedPointU8::new(1),
|
||||||
|
matrix: tkhd::Matrix::default(),
|
||||||
|
next_track_id: 1,
|
||||||
};
|
};
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
src_box.write_box(&mut buf).unwrap();
|
src_box.write_box(&mut buf).unwrap();
|
||||||
|
@ -176,6 +238,9 @@ mod tests {
|
||||||
timescale: 1000,
|
timescale: 1000,
|
||||||
duration: 634634,
|
duration: 634634,
|
||||||
rate: FixedPointU16::new(1),
|
rate: FixedPointU16::new(1),
|
||||||
|
volume: FixedPointU8::new(1),
|
||||||
|
matrix: tkhd::Matrix::default(),
|
||||||
|
next_track_id: 1,
|
||||||
};
|
};
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
src_box.write_box(&mut buf).unwrap();
|
src_box.write_box(&mut buf).unwrap();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||||
|
use serde::Serialize;
|
||||||
use std::io::{Read, Seek, Write};
|
use std::io::{Read, Seek, Write};
|
||||||
use serde::{Serialize};
|
|
||||||
|
|
||||||
use crate::mp4box::*;
|
use crate::mp4box::*;
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ impl Default for TkhdBox {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Default, Serialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||||
pub struct Matrix {
|
pub struct Matrix {
|
||||||
pub a: i32,
|
pub a: i32,
|
||||||
pub b: i32,
|
pub b: i32,
|
||||||
|
@ -64,6 +64,33 @@ pub struct Matrix {
|
||||||
pub w: i32,
|
pub w: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Matrix {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x}",
|
||||||
|
self.a, self.b, self.u, self.c, self.d, self.v, self.x, self.y, self.w
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Matrix {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
// unity matrix according to ISO/IEC 14496-12:2005(E)
|
||||||
|
a: 0x00010000,
|
||||||
|
b: 0,
|
||||||
|
u: 0,
|
||||||
|
c: 0,
|
||||||
|
d: 0x00010000,
|
||||||
|
v: 0,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
w: 0x40000000,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TkhdBox {
|
impl TkhdBox {
|
||||||
pub fn get_type(&self) -> BoxType {
|
pub fn get_type(&self) -> BoxType {
|
||||||
BoxType::TkhdBox
|
BoxType::TkhdBox
|
||||||
|
@ -103,9 +130,17 @@ impl Mp4Box for TkhdBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn summary(&self) -> Result<String> {
|
fn summary(&self) -> Result<String> {
|
||||||
let s = format!("creation_time={} track_id={} duration={} layer={} volume={} width={} height={}",
|
let s = format!(
|
||||||
self.creation_time, self.track_id, self.duration, self.layer,
|
"creation_time={} track_id={} duration={} layer={} volume={} matrix={} width={} height={}",
|
||||||
self.volume.value(), self.width.value(), self.height.value());
|
self.creation_time,
|
||||||
|
self.track_id,
|
||||||
|
self.duration,
|
||||||
|
self.layer,
|
||||||
|
self.volume.value(),
|
||||||
|
self.matrix,
|
||||||
|
self.width.value(),
|
||||||
|
self.height.value()
|
||||||
|
);
|
||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +177,7 @@ impl<R: Read + Seek> ReadBox<&mut R> for TkhdBox {
|
||||||
|
|
||||||
reader.read_u16::<BigEndian>()?; // reserved
|
reader.read_u16::<BigEndian>()?; // reserved
|
||||||
let matrix = Matrix {
|
let matrix = Matrix {
|
||||||
a: reader.read_i32::<byteorder::LittleEndian>()?,
|
a: reader.read_i32::<BigEndian>()?,
|
||||||
b: reader.read_i32::<BigEndian>()?,
|
b: reader.read_i32::<BigEndian>()?,
|
||||||
u: reader.read_i32::<BigEndian>()?,
|
u: reader.read_i32::<BigEndian>()?,
|
||||||
c: reader.read_i32::<BigEndian>()?,
|
c: reader.read_i32::<BigEndian>()?,
|
||||||
|
@ -205,7 +240,7 @@ impl<W: Write> WriteBox<&mut W> for TkhdBox {
|
||||||
|
|
||||||
writer.write_u16::<BigEndian>(0)?; // reserved
|
writer.write_u16::<BigEndian>(0)?; // reserved
|
||||||
|
|
||||||
writer.write_i32::<byteorder::LittleEndian>(self.matrix.a)?;
|
writer.write_i32::<BigEndian>(self.matrix.a)?;
|
||||||
writer.write_i32::<BigEndian>(self.matrix.b)?;
|
writer.write_i32::<BigEndian>(self.matrix.b)?;
|
||||||
writer.write_i32::<BigEndian>(self.matrix.u)?;
|
writer.write_i32::<BigEndian>(self.matrix.u)?;
|
||||||
writer.write_i32::<BigEndian>(self.matrix.c)?;
|
writer.write_i32::<BigEndian>(self.matrix.c)?;
|
||||||
|
@ -240,17 +275,7 @@ mod tests {
|
||||||
layer: 0,
|
layer: 0,
|
||||||
alternate_group: 0,
|
alternate_group: 0,
|
||||||
volume: FixedPointU8::new(1),
|
volume: FixedPointU8::new(1),
|
||||||
matrix: Matrix {
|
matrix: Matrix::default(),
|
||||||
a: 0x00010000,
|
|
||||||
b: 0,
|
|
||||||
u: 0,
|
|
||||||
c: 0,
|
|
||||||
d: 0x00010000,
|
|
||||||
v: 0,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
w: 0x40000000,
|
|
||||||
},
|
|
||||||
width: FixedPointU16::new(512),
|
width: FixedPointU16::new(512),
|
||||||
height: FixedPointU16::new(288),
|
height: FixedPointU16::new(288),
|
||||||
};
|
};
|
||||||
|
@ -279,17 +304,7 @@ mod tests {
|
||||||
layer: 0,
|
layer: 0,
|
||||||
alternate_group: 0,
|
alternate_group: 0,
|
||||||
volume: FixedPointU8::new(1),
|
volume: FixedPointU8::new(1),
|
||||||
matrix: Matrix {
|
matrix: Matrix::default(),
|
||||||
a: 0x00010000,
|
|
||||||
b: 0,
|
|
||||||
u: 0,
|
|
||||||
c: 0,
|
|
||||||
d: 0x00010000,
|
|
||||||
v: 0,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
w: 0x40000000,
|
|
||||||
},
|
|
||||||
width: FixedPointU16::new(512),
|
width: FixedPointU16::new(512),
|
||||||
height: FixedPointU16::new(288),
|
height: FixedPointU16::new(288),
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue