Fix truncated rips on dual-layer discs, propagate read errors
Use UDF file_extents() to read actual allocation descriptors instead of assuming m2ts files are contiguous from file_start_lba. Dual-layer UHD discs split large files across 70+ extents (~1 GB each) — the old code created one extent from packet count which only covered the first chunk, causing silent truncation at ~37%. Also changed fill_extents() to return io::Result<bool> so read errors propagate instead of being silently treated as EOF.
This commit is contained in:
+9
-8
@@ -66,20 +66,21 @@ impl Disc {
|
||||
pkt_count = clip_info.source_packet_count;
|
||||
total_size += pkt_count as u64 * 192;
|
||||
|
||||
// Get m2ts file start LBA and compute extent from packet count.
|
||||
// BD-ROM m2ts files are contiguous on disc (mastering requirement).
|
||||
// Get m2ts file extents from UDF allocation descriptors.
|
||||
// Dual-layer discs split files across layers — UDF knows the real layout.
|
||||
let m2ts_path = format!("/BDMV/STREAM/{}.m2ts", play_item.clip_id);
|
||||
let file_lba = udf_fs.file_start_lba(reader, &m2ts_path).unwrap_or(0);
|
||||
let total_bytes = pkt_count as u64 * 192;
|
||||
let total_sectors = total_bytes.div_ceil(2048) as u32;
|
||||
if total_sectors > 0 && file_lba > 0 {
|
||||
if let Ok(file_exts) = udf_fs.file_extents(reader, &m2ts_path) {
|
||||
for (lba, sectors) in file_exts {
|
||||
if sectors > 0 && lba > 0 {
|
||||
extents.push(Extent {
|
||||
start_lba: file_lba,
|
||||
sector_count: total_sectors,
|
||||
start_lba: lba,
|
||||
sector_count: sectors,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clips.push(Clip {
|
||||
clip_id: play_item.clip_id.clone(),
|
||||
|
||||
+6
-12
@@ -117,9 +117,9 @@ impl DiscStream {
|
||||
self.disc.as_ref()
|
||||
}
|
||||
|
||||
fn fill_extents(&mut self) -> bool {
|
||||
fn fill_extents(&mut self) -> io::Result<bool> {
|
||||
if self.current_extent >= self.extents.len() {
|
||||
return false;
|
||||
return Ok(false);
|
||||
}
|
||||
let ext_start = self.extents[self.current_extent].start_lba;
|
||||
let ext_sectors = self.extents[self.current_extent].sector_count;
|
||||
@@ -137,21 +137,15 @@ impl DiscStream {
|
||||
let bytes = sectors as usize * 2048;
|
||||
self.read_buf.resize(bytes, 0);
|
||||
|
||||
match self
|
||||
.reader
|
||||
.read_sectors(lba, sectors, &mut self.read_buf[..bytes])
|
||||
{
|
||||
Ok(_) => {
|
||||
self.reader
|
||||
.read_sectors(lba, sectors, &mut self.read_buf[..bytes])?;
|
||||
self.buf_valid = bytes;
|
||||
self.current_offset += sectors as u32;
|
||||
if self.current_offset >= ext_sectors {
|
||||
self.current_extent += 1;
|
||||
self.current_offset = 0;
|
||||
}
|
||||
true
|
||||
}
|
||||
Err(_) => false,
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +160,7 @@ impl crate::pes::Stream for DiscStream {
|
||||
}
|
||||
|
||||
loop {
|
||||
if !self.fill_extents() {
|
||||
if !self.fill_extents()? {
|
||||
self.eof = true;
|
||||
// Flush demuxer — last PES packet may still be in the assembler
|
||||
if let Some(ref mut demuxer) = self.ts_demuxer {
|
||||
|
||||
Reference in New Issue
Block a user