Add PES frame types and FileSectorReader — foundation for stream refactor
- pes.rs: PesFrame, InputStream, OutputStream traits - sector.rs: SectorReader now public, added FileSectorReader (ISO = file) - Foundation for unified DiscStream that handles both disc and ISO
This commit is contained in:
+9
-7
@@ -79,26 +79,29 @@ pub mod keydb;
|
||||
pub(crate) mod labels;
|
||||
pub(crate) mod mpls;
|
||||
pub mod mux;
|
||||
pub mod pes;
|
||||
pub(crate) mod platform;
|
||||
pub mod profile;
|
||||
pub mod scsi;
|
||||
pub(crate) mod sector;
|
||||
pub mod sector;
|
||||
pub(crate) mod speed;
|
||||
pub(crate) mod udf;
|
||||
|
||||
pub use drive::capture::{
|
||||
capture_drive_data, mask_bytes, mask_string, CapturedFeature, DriveCapture,
|
||||
};
|
||||
pub use drive::{find_drive, find_drives, Drive, DriveStatus};
|
||||
pub use drive::capture::{DriveCapture, CapturedFeature, capture_drive_data, mask_string, mask_bytes};
|
||||
pub use error::{Error, Result};
|
||||
pub use event::{Event, EventKind};
|
||||
pub use identity::DriveId;
|
||||
pub use profile::DriveProfile;
|
||||
// Platform trait is pub(crate) -- callers use Drive, not Platform directly
|
||||
pub use decrypt::{decrypt_sectors, DecryptKeys};
|
||||
pub use disc::{
|
||||
AacsState, AudioStream, Clip, Codec, ColorSpace, ContentFormat, ContentReader, Disc,
|
||||
DiscFormat, DiscTitle, Extent, HdrFormat, KeySource, ScanOptions, Stream, SubtitleStream,
|
||||
VideoStream,
|
||||
AacsState, AudioChannels, AudioStream, Clip, Codec, ColorSpace, ContentFormat,
|
||||
Disc, DiscFormat, DiscTitle, Extent, FrameRate, HdrFormat, KeySource, Resolution, SampleRate,
|
||||
ScanOptions, Stream, SubtitleStream, VideoStream,
|
||||
};
|
||||
pub use mux::DiscOptions;
|
||||
pub use mux::DiscStream;
|
||||
pub use mux::IOStream;
|
||||
pub use mux::IsoStream;
|
||||
@@ -108,7 +111,6 @@ pub use mux::NetworkStream;
|
||||
pub use mux::NullStream;
|
||||
pub use mux::StdioStream;
|
||||
pub use mux::{open_input, open_output, parse_url, InputOptions, StreamUrl};
|
||||
pub use decrypt::{DecryptKeys, decrypt_sectors};
|
||||
pub use scsi::ScsiTransport;
|
||||
pub use sector::SectorReader;
|
||||
pub use speed::DriveSpeed;
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
//! PES frame — the universal intermediate format.
|
||||
//!
|
||||
//! Every input stream produces PES frames. Every output stream consumes them.
|
||||
//! The pipeline just moves frames: input.next_frame() → output.write_frame().
|
||||
//!
|
||||
//! A PES frame is one unit of elementary stream data: a video frame,
|
||||
//! an audio frame, a subtitle packet. It has a track ID, timestamp,
|
||||
//! and the raw codec data.
|
||||
|
||||
/// One frame of elementary stream data.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PesFrame {
|
||||
/// Track index (0-based, matches StreamInfo track order).
|
||||
pub track: usize,
|
||||
/// Presentation timestamp in nanoseconds.
|
||||
pub pts: i64,
|
||||
/// True if this is a keyframe (IDR for video).
|
||||
pub keyframe: bool,
|
||||
/// Raw elementary stream data (NAL units, audio samples, etc).
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
/// Input stream — produces PES frames from any source.
|
||||
pub trait InputStream {
|
||||
/// Get the next frame. Returns None at end of stream.
|
||||
fn next_frame(&mut self) -> std::io::Result<Option<PesFrame>>;
|
||||
|
||||
/// Stream metadata (tracks, duration, etc).
|
||||
fn info(&self) -> &crate::disc::DiscTitle;
|
||||
}
|
||||
|
||||
/// Output stream — consumes PES frames to any destination.
|
||||
pub trait OutputStream {
|
||||
/// Write one frame.
|
||||
fn write_frame(&mut self, frame: &PesFrame) -> std::io::Result<()>;
|
||||
|
||||
/// Finalize (flush, write index, close).
|
||||
fn finish(&mut self) -> std::io::Result<()>;
|
||||
}
|
||||
+40
-1
@@ -7,8 +7,47 @@
|
||||
use crate::error::Result;
|
||||
|
||||
/// Read 2048-byte sectors from a disc or disc image.
|
||||
pub trait SectorReader {
|
||||
pub trait SectorReader: Send {
|
||||
/// Read `count` sectors starting at `lba` into `buf`.
|
||||
/// `buf` must be at least `count * 2048` bytes.
|
||||
fn read_sectors(&mut self, lba: u32, count: u16, buf: &mut [u8]) -> Result<usize>;
|
||||
|
||||
/// Total capacity in sectors, if known.
|
||||
fn capacity(&self) -> u32 { 0 }
|
||||
}
|
||||
|
||||
/// SectorReader backed by a file (ISO image).
|
||||
/// Seeks to lba * 2048, reads count * 2048 bytes.
|
||||
pub struct FileSectorReader {
|
||||
file: std::io::BufReader<std::fs::File>,
|
||||
capacity: u32,
|
||||
}
|
||||
|
||||
impl FileSectorReader {
|
||||
pub fn open(path: &str) -> std::io::Result<Self> {
|
||||
let file = std::fs::File::open(path)?;
|
||||
let len = file.metadata()?.len();
|
||||
let capacity = (len / 2048) as u32;
|
||||
Ok(Self {
|
||||
file: std::io::BufReader::with_capacity(4 * 1024 * 1024, file),
|
||||
capacity,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl SectorReader for FileSectorReader {
|
||||
fn read_sectors(&mut self, lba: u32, count: u16, buf: &mut [u8]) -> Result<usize> {
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
let offset = lba as u64 * 2048;
|
||||
let bytes = count as usize * 2048;
|
||||
self.file.seek(SeekFrom::Start(offset))
|
||||
.map_err(|e| crate::error::Error::IoError { source: e })?;
|
||||
self.file.read_exact(&mut buf[..bytes])
|
||||
.map_err(|e| crate::error::Error::IoError { source: e })?;
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
fn capacity(&self) -> u32 {
|
||||
self.capacity
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user