diff options
Diffstat (limited to 'remuxer/src/fragment.rs')
-rw-r--r-- | remuxer/src/fragment.rs | 152 |
1 files changed, 59 insertions, 93 deletions
diff --git a/remuxer/src/fragment.rs b/remuxer/src/fragment.rs index c7954b0..9fa68f3 100644 --- a/remuxer/src/fragment.rs +++ b/remuxer/src/fragment.rs @@ -5,16 +5,12 @@ */ use crate::{ - metadata::matroska_metadata, seek_index::get_seek_index, segment_extractor::SegmentExtractIter, + ebml_header, ebml_segment_info, ebml_track_entry, seek_index::get_seek_index, + segment_extractor::SegmentExtractIter, }; use anyhow::{anyhow, Context, Result}; -use ebml_struct::{ - matroska::{BlockGroup, Cluster, Ebml, Info, Segment, Tracks}, - write::TagWrite, - Block, -}; use jellybase::common::{LocalTrack, Node, SourceTrackKind}; -use jellymatroska::{read::EbmlReader, Master, MatroskaTag}; +use jellymatroska::{read::EbmlReader, write::EbmlWriter, Master, MatroskaTag}; use log::{debug, info}; use std::{ fs::File, @@ -92,7 +88,7 @@ pub fn write_fragment_into( n: usize, ) -> anyhow::Result<()> { info!("writing fragment {n} of {:?} (track {track})", item.title); - + let mut output = EbmlWriter::new(BufWriter::new(writer), 0); let media_info = item.media.as_ref().unwrap(); let info = media_info .tracks @@ -150,101 +146,71 @@ pub fn write_fragment_into( .map(|b| b.pts) .unwrap_or((media_info.duration * 1000.) as u64); - let input_metadata = (*matroska_metadata(&local_track.path)?).clone().unwrap(); + output.write_tag(&ebml_header(webm))?; + output.write_tag(&MatroskaTag::Segment(Master::Start))?; + output.write_tag(&ebml_segment_info( + format!("{}: {info}", item.title.clone().unwrap_or_default()), + (last_block_pts - start_block.pts) as f64 / 1000., + ))?; + output.write_tag(&MatroskaTag::Tracks(Master::Collected(vec![ + ebml_track_entry( + mapped, + local_track.track as u64 * 100, // TODO something else that is unique to the track + &info, + local_track.codec_private.clone(), + ), + ])))?; reader.seek(start_block.source_off, MatroskaTag::Cluster(Master::Start))?; let mut reader = SegmentExtractIter::new(&mut reader, local_track.track as u64); - let mut cluster = Cluster::default(); - cluster.timestamp = start_block.pts; - for i in start_block_index..end_block_index { - let index_block = &index.blocks[i]; - let (block, duration) = reader.next_block()?; + { + // TODO this one caused fragments to get dropped by MSE for no reason + // for i in start_block_index..end_block_index { + // let index_block = &index.blocks[i]; + // let (mut block, duration) = reader.next()?; - let mut block = Block { - data: block.data, - discardable: block.discardable, - invisible: block.invisible, - keyframe: block.keyframe, - lacing: block.lacing.map(|l| match l { - jellymatroska::block::LacingType::Xiph => ebml_struct::LacingType::Xiph, - jellymatroska::block::LacingType::FixedSize => ebml_struct::LacingType::FixedSize, - jellymatroska::block::LacingType::Ebml => ebml_struct::LacingType::Ebml, - }), - timestamp_off: block.timestamp_off, - track: block.track, - }; + // assert_eq!(index_block.size, block.data.len(), "seek index is wrong"); - assert_eq!(index_block.size, block.data.len(), "seek index is wrong"); - - block.track = 1; - // TODO this does generate overflows sometimes - block.timestamp_off = (index_block.pts as i64 - start_block.pts as i64) - .try_into() - .unwrap(); - if let Some(duration) = duration { - cluster.block_groups.push(BlockGroup { - block_duration: Some(duration), - block, - ..Default::default() - }) - } else { - cluster.simple_blocks.push(block) - } + // block.track = 1; + // block.timestamp_off = 0; + // output.write_tag(&MatroskaTag::Cluster(Master::Collected(vec![ + // MatroskaTag::Timestamp(index_block.pts - start_block.pts), + // if let Some(duration) = duration { + // MatroskaTag::BlockGroup(Master::Collected(vec![ + // MatroskaTag::BlockDuration(duration), + // MatroskaTag::Block(block), + // ])) + // } else { + // MatroskaTag::SimpleBlock(block) + // }, + // ])))?; + // } } + { + let mut blocks = vec![MatroskaTag::Timestamp(start_block.pts)]; + for i in start_block_index..end_block_index { + let index_block = &index.blocks[i]; + let (mut block, duration) = reader.next_block()?; - let mut input_track = input_metadata - .tracks - .unwrap() - .entries - .into_iter() - .find(|t| t.track_number == local_track.track as u64) - .unwrap(); + assert_eq!(index_block.size, block.data.len(), "seek index is wrong"); - input_track.track_number = 1; - if webm { - if let Some(v) = &mut input_track.video { - v.colour = None; + block.track = 1; + // TODO this does generate overflows sometimes + block.timestamp_off = (index_block.pts as i64 - start_block.pts as i64) + .try_into() + .unwrap(); + if let Some(duration) = duration { + blocks.push(MatroskaTag::BlockGroup(Master::Collected(vec![ + MatroskaTag::BlockDuration(duration), + MatroskaTag::Block(block), + ]))) + } else { + blocks.push(MatroskaTag::SimpleBlock(block)) + } } + output.write_tag(&MatroskaTag::Cluster(Master::Collected(blocks)))?; } - - let mut output = BufWriter::new(writer); - - Ebml { - ebml_version: 1, - ebml_read_version: 1, - ebml_max_id_length: 4, - ebml_max_size_length: 8, - doc_type: if webm { - "webm".to_string() - } else { - "matroska".to_string() - }, - doc_type_version: 4, - doc_type_read_version: 2, - doc_type_extensions: vec![], - } - .write(&mut output)?; - - Segment { - info: Info { - timestamp_scale: 1_000_000, - duration: Some((last_block_pts - start_block.pts) as f64), - title: Some(format!( - "{}: {info}", - item.title.clone().unwrap_or_default() - )), - muxing_app: "ebml-struct".to_owned(), - writing_app: "jellything".to_owned(), - ..Default::default() - }, - tracks: Some(Tracks { - entries: vec![input_track], - }), - clusters: vec![cluster], - ..Default::default() - } - .write(&mut output)?; - + debug!("wrote {} bytes", output.position()); Ok(()) } |