mirror of
https://github.com/alfg/mp4-rust.git
synced 2025-01-03 00:48:40 +00:00
Mp4Writer should use co64 by default, then convert to stco is possible for compatibility (#71)
This commit is contained in:
parent
7218ada431
commit
33959766d4
2 changed files with 50 additions and 37 deletions
|
@ -1,6 +1,6 @@
|
|||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||
use serde::Serialize;
|
||||
use std::io::{Read, Seek, Write};
|
||||
use serde::{Serialize};
|
||||
|
||||
use crate::mp4box::*;
|
||||
|
||||
|
@ -81,6 +81,24 @@ impl<W: Write> WriteBox<&mut W> for StcoBox {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<&co64::Co64Box> for StcoBox {
|
||||
type Error = std::num::TryFromIntError;
|
||||
|
||||
fn try_from(co64: &co64::Co64Box) -> std::result::Result<Self, Self::Error> {
|
||||
let entries = co64
|
||||
.entries
|
||||
.iter()
|
||||
.copied()
|
||||
.map(|x| u32::try_from(x))
|
||||
.collect::<std::result::Result<Vec<_>, _>>()?;
|
||||
Ok(Self {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
entries,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
63
src/track.rs
63
src/track.rs
|
@ -4,22 +4,12 @@ use std::convert::TryFrom;
|
|||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::mp4box::trak::TrakBox;
|
||||
use crate::mp4box::traf::TrafBox;
|
||||
use crate::mp4box::trak::TrakBox;
|
||||
use crate::mp4box::{
|
||||
avc1::Avc1Box,
|
||||
hev1::Hev1Box,
|
||||
vp09::Vp09Box,
|
||||
ctts::CttsBox,
|
||||
ctts::CttsEntry,
|
||||
mp4a::Mp4aBox,
|
||||
smhd::SmhdBox,
|
||||
stco::StcoBox,
|
||||
stsc::StscEntry,
|
||||
stss::StssBox,
|
||||
stts::SttsEntry,
|
||||
tx3g::Tx3gBox,
|
||||
vmhd::VmhdBox,
|
||||
avc1::Avc1Box, co64::Co64Box, ctts::CttsBox, ctts::CttsEntry, hev1::Hev1Box, mp4a::Mp4aBox,
|
||||
smhd::SmhdBox, stco::StcoBox, stsc::StscEntry, stss::StssBox, stts::SttsEntry, tx3g::Tx3gBox,
|
||||
vmhd::VmhdBox, vp09::Vp09Box,
|
||||
};
|
||||
use crate::*;
|
||||
|
||||
|
@ -110,7 +100,11 @@ pub struct Mp4Track {
|
|||
impl Mp4Track {
|
||||
pub(crate) fn from(trak: &TrakBox) -> Self {
|
||||
let trak = trak.clone();
|
||||
Self { trak, trafs: Vec::new(), default_sample_duration: 0, }
|
||||
Self {
|
||||
trak,
|
||||
trafs: Vec::new(),
|
||||
default_sample_duration: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn track_id(&self) -> u32 {
|
||||
|
@ -382,7 +376,13 @@ impl Mp4Track {
|
|||
fn sample_size(&self, sample_id: u32) -> Result<u32> {
|
||||
if self.trafs.len() > 0 {
|
||||
if let Some((traf_idx, sample_idx)) = self.find_traf_idx_and_sample_idx(sample_id) {
|
||||
if let Some(size) = self.trafs[traf_idx].trun.as_ref().unwrap().sample_sizes.get(sample_idx) {
|
||||
if let Some(size) = self.trafs[traf_idx]
|
||||
.trun
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.sample_sizes
|
||||
.get(sample_idx)
|
||||
{
|
||||
Ok(*size)
|
||||
} else {
|
||||
Err(Error::EntryInTrunNotFound(
|
||||
|
@ -392,10 +392,7 @@ impl Mp4Track {
|
|||
))
|
||||
}
|
||||
} else {
|
||||
Err(Error::BoxInTrafNotFound(
|
||||
self.track_id(),
|
||||
BoxType::TrafBox,
|
||||
))
|
||||
Err(Error::BoxInTrafNotFound(self.track_id(), BoxType::TrafBox))
|
||||
}
|
||||
} else {
|
||||
let stsz = &self.trak.mdia.minf.stbl.stsz;
|
||||
|
@ -432,10 +429,7 @@ impl Mp4Track {
|
|||
if let Some((traf_idx, _sample_idx)) = self.find_traf_idx_and_sample_idx(sample_id) {
|
||||
Ok(self.trafs[traf_idx].tfhd.base_data_offset as u64)
|
||||
} else {
|
||||
Err(Error::BoxInTrafNotFound(
|
||||
self.track_id(),
|
||||
BoxType::TrafBox,
|
||||
))
|
||||
Err(Error::BoxInTrafNotFound(self.track_id(), BoxType::TrafBox))
|
||||
}
|
||||
} else {
|
||||
let stsc_index = self.stsc_index(sample_id)?;
|
||||
|
@ -470,7 +464,7 @@ impl Mp4Track {
|
|||
|
||||
if self.trafs.len() > 0 {
|
||||
let start_time = ((sample_id - 1) * self.default_sample_duration) as u64;
|
||||
return Ok((start_time, self.default_sample_duration))
|
||||
return Ok((start_time, self.default_sample_duration));
|
||||
} else {
|
||||
for entry in stts.entries.iter() {
|
||||
if sample_id <= sample_count + entry.sample_count - 1 {
|
||||
|
@ -504,7 +498,7 @@ impl Mp4Track {
|
|||
fn is_sync_sample(&self, sample_id: u32) -> bool {
|
||||
if self.trafs.len() > 0 {
|
||||
let sample_sizes_count = self.sample_count() / self.trafs.len() as u32;
|
||||
return sample_id == 1 || sample_id % sample_sizes_count == 0
|
||||
return sample_id == 1 || sample_id % sample_sizes_count == 0;
|
||||
}
|
||||
|
||||
if let Some(ref stss) = self.trak.mdia.minf.stbl.stss {
|
||||
|
@ -570,8 +564,7 @@ impl Mp4TrackWriter {
|
|||
trak.mdia.mdhd.timescale = config.timescale;
|
||||
trak.mdia.mdhd.language = config.language.to_owned();
|
||||
trak.mdia.hdlr.handler_type = config.track_type.into();
|
||||
// XXX largesize
|
||||
trak.mdia.minf.stbl.stco = Some(StcoBox::default());
|
||||
trak.mdia.minf.stbl.co64 = Some(Co64Box::default());
|
||||
match config.media_conf {
|
||||
MediaConfig::AvcConfig(ref avc_config) => {
|
||||
trak.tkhd.set_width(avc_config.width);
|
||||
|
@ -610,7 +603,6 @@ impl Mp4TrackWriter {
|
|||
let tx3g = Tx3gBox::default();
|
||||
trak.mdia.minf.stbl.stsd.tx3g = Some(tx3g);
|
||||
}
|
||||
|
||||
}
|
||||
Ok(Mp4TrackWriter {
|
||||
trak,
|
||||
|
@ -761,10 +753,9 @@ impl Mp4TrackWriter {
|
|||
Ok(self.trak.tkhd.duration)
|
||||
}
|
||||
|
||||
// XXX largesize
|
||||
fn chunk_count(&self) -> u32 {
|
||||
let stco = self.trak.mdia.minf.stbl.stco.as_ref().unwrap();
|
||||
stco.entries.len() as u32
|
||||
let co64 = self.trak.mdia.minf.stbl.co64.as_ref().unwrap();
|
||||
co64.entries.len() as u32
|
||||
}
|
||||
|
||||
fn update_sample_to_chunk(&mut self, chunk_id: u32) {
|
||||
|
@ -784,8 +775,8 @@ impl Mp4TrackWriter {
|
|||
}
|
||||
|
||||
fn update_chunk_offsets(&mut self, offset: u64) {
|
||||
let stco = self.trak.mdia.minf.stbl.stco.as_mut().unwrap();
|
||||
stco.entries.push(offset as u32);
|
||||
let co64 = self.trak.mdia.minf.stbl.co64.as_mut().unwrap();
|
||||
co64.entries.push(offset);
|
||||
}
|
||||
|
||||
fn write_chunk<W: Write + Seek>(&mut self, writer: &mut W) -> Result<()> {
|
||||
|
@ -830,6 +821,10 @@ impl Mp4TrackWriter {
|
|||
// mp4a.esds.es_desc.dec_config.max_bitrate
|
||||
// mp4a.esds.es_desc.dec_config.avg_bitrate
|
||||
}
|
||||
if let Ok(stco) = StcoBox::try_from(self.trak.mdia.minf.stbl.co64.as_ref().unwrap()) {
|
||||
self.trak.mdia.minf.stbl.stco = Some(stco);
|
||||
self.trak.mdia.minf.stbl.co64 = None;
|
||||
}
|
||||
|
||||
Ok(self.trak.clone())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue