PES pipeline: InputStream on DiscStream + IsoStream, MkvOutputStream
- DiscStream: next_frame() reads sectors → decrypts → demuxes → returns PesFrame - IsoStream: same pattern, reads from ISO file - MkvOutputStream: accepts PesFrame, writes MKV via MkvMuxer - InputStream trait: next_frame(), info(), codec_private(), headers_ready() - OutputStream trait: write_frame(), finish() - FileSectorReader: SectorReader backed by a file - PesFrame: track + pts + keyframe + data Old Read/Write IOStream impls preserved for backward compatibility. Next: replace pipe() in CLI to use PES pipeline.
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
//! MKV output stream — accepts PES frames, writes Matroska container.
|
||||
//!
|
||||
//! Implements OutputStream. Takes PES frames directly — no TS demuxing needed.
|
||||
//! Creates the MKV muxer once codec_private is provided for all tracks.
|
||||
|
||||
use super::mkv::{MkvMuxer, MkvTrack};
|
||||
use super::WriteSeek;
|
||||
use crate::disc::DiscTitle;
|
||||
use crate::pes::{OutputStream, PesFrame};
|
||||
use std::io;
|
||||
|
||||
pub struct MkvOutputStream {
|
||||
muxer: Option<MkvMuxer<Box<dyn WriteSeek>>>,
|
||||
}
|
||||
|
||||
impl MkvOutputStream {
|
||||
/// Create an MKV output stream.
|
||||
/// `codec_privates` provides initialization data per track (from InputStream).
|
||||
/// Tracks without codec_private get None.
|
||||
pub fn create(
|
||||
writer: Box<dyn WriteSeek>,
|
||||
title: &DiscTitle,
|
||||
codec_privates: &[Option<Vec<u8>>],
|
||||
) -> io::Result<Self> {
|
||||
let mut tracks = Vec::new();
|
||||
for (idx, s) in title.streams.iter().enumerate() {
|
||||
let mut track = match s {
|
||||
crate::disc::Stream::Video(v) => MkvTrack::video(v),
|
||||
crate::disc::Stream::Audio(a) => MkvTrack::audio(a),
|
||||
crate::disc::Stream::Subtitle(s) => MkvTrack::subtitle(s),
|
||||
};
|
||||
if let Some(cp) = codec_privates.get(idx).and_then(|c| c.as_ref()) {
|
||||
track.codec_private = Some(cp.clone());
|
||||
}
|
||||
tracks.push(track);
|
||||
}
|
||||
|
||||
let muxer = MkvMuxer::new_with_chapters(
|
||||
writer,
|
||||
&tracks,
|
||||
Some(&title.playlist),
|
||||
title.duration_secs,
|
||||
&title.chapters,
|
||||
)?;
|
||||
|
||||
Ok(Self { muxer: Some(muxer) })
|
||||
}
|
||||
}
|
||||
|
||||
impl OutputStream for MkvOutputStream {
|
||||
fn write_frame(&mut self, frame: &PesFrame) -> io::Result<()> {
|
||||
if let Some(ref mut muxer) = self.muxer {
|
||||
muxer.write_frame(frame.track, frame.pts, frame.keyframe, &frame.data)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn finish(&mut self) -> io::Result<()> {
|
||||
if let Some(muxer) = self.muxer.take() {
|
||||
muxer.finish()
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user