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 labels;
|
||||||
pub(crate) mod mpls;
|
pub(crate) mod mpls;
|
||||||
pub mod mux;
|
pub mod mux;
|
||||||
|
pub mod pes;
|
||||||
pub(crate) mod platform;
|
pub(crate) mod platform;
|
||||||
pub mod profile;
|
pub mod profile;
|
||||||
pub mod scsi;
|
pub mod scsi;
|
||||||
pub(crate) mod sector;
|
pub mod sector;
|
||||||
pub(crate) mod speed;
|
pub(crate) mod speed;
|
||||||
pub(crate) mod udf;
|
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::{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 error::{Error, Result};
|
||||||
pub use event::{Event, EventKind};
|
pub use event::{Event, EventKind};
|
||||||
pub use identity::DriveId;
|
pub use identity::DriveId;
|
||||||
pub use profile::DriveProfile;
|
pub use profile::DriveProfile;
|
||||||
// Platform trait is pub(crate) -- callers use Drive, not Platform directly
|
// Platform trait is pub(crate) -- callers use Drive, not Platform directly
|
||||||
|
pub use decrypt::{decrypt_sectors, DecryptKeys};
|
||||||
pub use disc::{
|
pub use disc::{
|
||||||
AacsState, AudioStream, Clip, Codec, ColorSpace, ContentFormat, ContentReader, Disc,
|
AacsState, AudioChannels, AudioStream, Clip, Codec, ColorSpace, ContentFormat,
|
||||||
DiscFormat, DiscTitle, Extent, HdrFormat, KeySource, ScanOptions, Stream, SubtitleStream,
|
Disc, DiscFormat, DiscTitle, Extent, FrameRate, HdrFormat, KeySource, Resolution, SampleRate,
|
||||||
VideoStream,
|
ScanOptions, Stream, SubtitleStream, VideoStream,
|
||||||
};
|
};
|
||||||
pub use mux::DiscOptions;
|
|
||||||
pub use mux::DiscStream;
|
pub use mux::DiscStream;
|
||||||
pub use mux::IOStream;
|
pub use mux::IOStream;
|
||||||
pub use mux::IsoStream;
|
pub use mux::IsoStream;
|
||||||
@@ -108,7 +111,6 @@ pub use mux::NetworkStream;
|
|||||||
pub use mux::NullStream;
|
pub use mux::NullStream;
|
||||||
pub use mux::StdioStream;
|
pub use mux::StdioStream;
|
||||||
pub use mux::{open_input, open_output, parse_url, InputOptions, StreamUrl};
|
pub use mux::{open_input, open_output, parse_url, InputOptions, StreamUrl};
|
||||||
pub use decrypt::{DecryptKeys, decrypt_sectors};
|
|
||||||
pub use scsi::ScsiTransport;
|
pub use scsi::ScsiTransport;
|
||||||
pub use sector::SectorReader;
|
pub use sector::SectorReader;
|
||||||
pub use speed::DriveSpeed;
|
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;
|
use crate::error::Result;
|
||||||
|
|
||||||
/// Read 2048-byte sectors from a disc or disc image.
|
/// 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`.
|
/// Read `count` sectors starting at `lba` into `buf`.
|
||||||
/// `buf` must be at least `count * 2048` bytes.
|
/// `buf` must be at least `count * 2048` bytes.
|
||||||
fn read_sectors(&mut self, lba: u32, count: u16, buf: &mut [u8]) -> Result<usize>;
|
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