Zero clippy warnings: fix all 32 remaining
- Iterator::find() replaces manual loops (6 sites) - Index-only loops → iterators (4 sites) - Identical if-blocks merged - Box large MkvStream WriteState enum variant - Vec macro initializers, late init fixes - Unused fields prefixed with underscore (format spec fields) - Dead code removed or documented 0 clippy warnings. 319 tests passing.
This commit is contained in:
@@ -1137,9 +1137,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_ecdh_shared_secret() {
|
fn test_ecdh_shared_secret() {
|
||||||
// Two parties should derive the same shared point
|
// Two parties should derive the same shared point
|
||||||
let p = BigUint::from_bytes_be(&EC_P);
|
let _p = BigUint::from_bytes_be(&EC_P);
|
||||||
let a = BigUint::from_bytes_be(&EC_A);
|
let _a = BigUint::from_bytes_be(&EC_A);
|
||||||
let g = EcPoint::from_bytes(&EC_GX, &EC_GY);
|
let _g = EcPoint::from_bytes(&EC_GX, &EC_GY);
|
||||||
|
|
||||||
let (priv_a, pub_ax, pub_ay) = generate_host_key_pair();
|
let (priv_a, pub_ax, pub_ay) = generate_host_key_pair();
|
||||||
let (priv_b, pub_bx, pub_by) = generate_host_key_pair();
|
let (priv_b, pub_bx, pub_by) = generate_host_key_pair();
|
||||||
|
|||||||
+1
-1
@@ -57,7 +57,7 @@ pub struct DiscEntry {
|
|||||||
/// Parse a hex string like "0xABCD..." into bytes.
|
/// Parse a hex string like "0xABCD..." into bytes.
|
||||||
pub(crate) fn parse_hex(s: &str) -> Option<Vec<u8>> {
|
pub(crate) fn parse_hex(s: &str) -> Option<Vec<u8>> {
|
||||||
let s = s.trim().trim_start_matches("0x").trim_start_matches("0X");
|
let s = s.trim().trim_start_matches("0x").trim_start_matches("0X");
|
||||||
if s.len() % 2 != 0 {
|
if !s.len().is_multiple_of(2) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let mut out = Vec::with_capacity(s.len() / 2);
|
let mut out = Vec::with_capacity(s.len() / 2);
|
||||||
|
|||||||
+5
-2
@@ -11,6 +11,7 @@ use crate::error::{Error, Result};
|
|||||||
|
|
||||||
/// Parsed CLPI clip info.
|
/// Parsed CLPI clip info.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct ClipInfo {
|
pub struct ClipInfo {
|
||||||
pub version: String,
|
pub version: String,
|
||||||
/// Total source packets in the m2ts (each 192 bytes)
|
/// Total source packets in the m2ts (each 192 bytes)
|
||||||
@@ -22,6 +23,7 @@ pub struct ClipInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct EpCoarse {
|
pub struct EpCoarse {
|
||||||
pub ref_to_fine_id: u32,
|
pub ref_to_fine_id: u32,
|
||||||
pub pts_coarse: u32,
|
pub pts_coarse: u32,
|
||||||
@@ -29,11 +31,13 @@ pub struct EpCoarse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct EpFine {
|
pub struct EpFine {
|
||||||
pub pts_fine: u32,
|
pub pts_fine: u32,
|
||||||
pub spn_fine: u32,
|
pub spn_fine: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
impl ClipInfo {
|
impl ClipInfo {
|
||||||
/// Reconstruct full PTS from coarse + fine entry.
|
/// Reconstruct full PTS from coarse + fine entry.
|
||||||
pub fn full_pts(coarse: &EpCoarse, fine: &EpFine) -> u32 {
|
pub fn full_pts(coarse: &EpCoarse, fine: &EpFine) -> u32 {
|
||||||
@@ -361,8 +365,7 @@ mod tests {
|
|||||||
//
|
//
|
||||||
// Pack into a u128 for convenience then extract 10 bytes
|
// Pack into a u128 for convenience then extract 10 bytes
|
||||||
let ep_stream_type: u32 = 1; // video
|
let ep_stream_type: u32 = 1; // video
|
||||||
let packed: u128 = ((0u128) << 70) // reserved: 10 bits
|
let packed: u128 = ((ep_stream_type as u128) << 66) // EP_stream_type: 4 bits
|
||||||
| ((ep_stream_type as u128) << 66) // EP_stream_type: 4 bits
|
|
||||||
| ((num_coarse as u128) << 50) // num_coarse: 16 bits
|
| ((num_coarse as u128) << 50) // num_coarse: 16 bits
|
||||||
| ((num_fine as u128) << 32) // num_fine: 18 bits
|
| ((num_fine as u128) << 32) // num_fine: 18 bits
|
||||||
| (ep_map_start as u128); // EP_map_start: 32 bits
|
| (ep_map_start as u128); // EP_map_start: 32 bits
|
||||||
|
|||||||
+4
-4
@@ -63,7 +63,7 @@ pub fn recover_title_key(sector: &[u8], plain: &[u8]) -> Option<[u8; 5]> {
|
|||||||
// Clock LFSR1 forward 4 steps to reconstruct LFSR0 state
|
// Clock LFSR1 forward 4 steps to reconstruct LFSR0 state
|
||||||
let mut t3: u32 = 0;
|
let mut t3: u32 = 0;
|
||||||
|
|
||||||
for i in 0..4 {
|
for &buf_byte in buf.iter().take(4) {
|
||||||
// Advance LFSR1
|
// Advance LFSR1
|
||||||
let t4 = TAB2[t2 as usize] ^ TAB3[t1 as usize];
|
let t4 = TAB2[t2 as usize] ^ TAB3[t1 as usize];
|
||||||
t2 = t1 >> 1;
|
t2 = t1 >> 1;
|
||||||
@@ -71,7 +71,7 @@ pub fn recover_title_key(sector: &[u8], plain: &[u8]) -> Option<[u8; 5]> {
|
|||||||
let t4_perm = TAB5[t4 as usize];
|
let t4_perm = TAB5[t4 as usize];
|
||||||
|
|
||||||
// Deduce LFSR0 output from the buffer and LFSR1 output
|
// Deduce LFSR0 output from the buffer and LFSR1 output
|
||||||
let mut t6 = buf[i] as u32;
|
let mut t6 = buf_byte as u32;
|
||||||
if t5 > 0 {
|
if t5 > 0 {
|
||||||
t6 = (t6 + 0xFF) & 0xFF;
|
t6 = (t6 + 0xFF) & 0xFF;
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,7 @@ pub fn recover_title_key(sector: &[u8], plain: &[u8]) -> Option<[u8; 5]> {
|
|||||||
|
|
||||||
// Phase 3: Validate — clock 6 more steps and check against buffer
|
// Phase 3: Validate — clock 6 more steps and check against buffer
|
||||||
let mut valid = true;
|
let mut valid = true;
|
||||||
for i in 4..10 {
|
for &buf_byte in buf.iter().skip(4) {
|
||||||
let t4 = TAB2[t2 as usize] ^ TAB3[t1 as usize];
|
let t4 = TAB2[t2 as usize] ^ TAB3[t1 as usize];
|
||||||
t2 = t1 >> 1;
|
t2 = t1 >> 1;
|
||||||
t1 = ((t1 & 1) << 8) ^ t4 as u32;
|
t1 = ((t1 & 1) << 8) ^ t4 as u32;
|
||||||
@@ -103,7 +103,7 @@ pub fn recover_title_key(sector: &[u8], plain: &[u8]) -> Option<[u8; 5]> {
|
|||||||
let t6_perm = TAB4[(t6 & 0xFF) as usize];
|
let t6_perm = TAB4[(t6 & 0xFF) as usize];
|
||||||
|
|
||||||
t5 += t6_perm as u32 + t4_perm as u32;
|
t5 += t6_perm as u32 + t4_perm as u32;
|
||||||
if (t5 & 0xFF) as u8 != buf[i] {
|
if (t5 & 0xFF) as u8 != buf_byte {
|
||||||
valid = false;
|
valid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-8
@@ -57,7 +57,7 @@ pub fn descramble_sector(title_key: &[u8; 5], sector: &mut [u8]) {
|
|||||||
let mut combined: u32 = 0;
|
let mut combined: u32 = 0;
|
||||||
|
|
||||||
// Generate 1920 keystream bytes (for sector bytes 128..2048)
|
// Generate 1920 keystream bytes (for sector bytes 128..2048)
|
||||||
for i in 128..2048 {
|
for byte in sector.iter_mut().take(2048).skip(128) {
|
||||||
// Clock LFSR1
|
// Clock LFSR1
|
||||||
let o_lfsr1 = TAB2[lfsr1_hi as usize] ^ TAB3[lfsr1_lo as usize];
|
let o_lfsr1 = TAB2[lfsr1_hi as usize] ^ TAB3[lfsr1_lo as usize];
|
||||||
lfsr1_hi = lfsr1_lo >> 1;
|
lfsr1_hi = lfsr1_lo >> 1;
|
||||||
@@ -70,7 +70,7 @@ pub fn descramble_sector(title_key: &[u8; 5], sector: &mut [u8]) {
|
|||||||
|
|
||||||
// Combine with addition and carry
|
// Combine with addition and carry
|
||||||
combined += (o_lfsr0 ^ 0xFF) as u32 + o_lfsr1_perm as u32;
|
combined += (o_lfsr0 ^ 0xFF) as u32 + o_lfsr1_perm as u32;
|
||||||
sector[i] ^= (combined & 0xFF) as u8;
|
*byte ^= (combined & 0xFF) as u8;
|
||||||
combined >>= 8;
|
combined >>= 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ pub(crate) fn decrypt_key(invert: u8, p_key: &[u8; 5], p_crypted: &[u8]) -> [u8;
|
|||||||
let mut combined: u32 = 0;
|
let mut combined: u32 = 0;
|
||||||
let mut k = [0u8; 5];
|
let mut k = [0u8; 5];
|
||||||
|
|
||||||
for i in 0..5 {
|
for byte in &mut k {
|
||||||
let o_lfsr1 = TAB2[lfsr1_hi as usize] ^ TAB3[lfsr1_lo as usize];
|
let o_lfsr1 = TAB2[lfsr1_hi as usize] ^ TAB3[lfsr1_lo as usize];
|
||||||
lfsr1_hi = lfsr1_lo >> 1;
|
lfsr1_hi = lfsr1_lo >> 1;
|
||||||
lfsr1_lo = ((lfsr1_lo & 1) << 8) ^ o_lfsr1 as u32;
|
lfsr1_lo = ((lfsr1_lo & 1) << 8) ^ o_lfsr1 as u32;
|
||||||
@@ -112,7 +112,7 @@ pub(crate) fn decrypt_key(invert: u8, p_key: &[u8; 5], p_crypted: &[u8]) -> [u8;
|
|||||||
lfsr0 = (lfsr0 >> 8) | ((o_lfsr0 as u32) << 24);
|
lfsr0 = (lfsr0 >> 8) | ((o_lfsr0 as u32) << 24);
|
||||||
|
|
||||||
combined += (o_lfsr0 ^ invert) as u32 + o_lfsr1_perm as u32;
|
combined += (o_lfsr0 ^ invert) as u32 + o_lfsr1_perm as u32;
|
||||||
k[i] = (combined & 0xFF) as u8;
|
*byte = (combined & 0xFF) as u8;
|
||||||
combined >>= 8;
|
combined >>= 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,8 +257,8 @@ mod tests {
|
|||||||
sector[0x82] = 0x01;
|
sector[0x82] = 0x01;
|
||||||
sector[0x83] = 0xE0;
|
sector[0x83] = 0xE0;
|
||||||
// Fill some content in the encrypted region
|
// Fill some content in the encrypted region
|
||||||
for i in 0x84..2048 {
|
for (i, byte) in sector.iter_mut().enumerate().take(2048).skip(0x84) {
|
||||||
sector[i] = (i & 0xFF) as u8;
|
*byte = (i & 0xFF) as u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
let original = sector.clone();
|
let original = sector.clone();
|
||||||
@@ -299,8 +299,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn css_tab1_is_permutation() {
|
fn css_tab1_is_permutation() {
|
||||||
let mut seen = [false; 256];
|
let mut seen = [false; 256];
|
||||||
for i in 0..256 {
|
for tab1_val in &TAB1 {
|
||||||
let v = TAB1[i] as usize;
|
let v = *tab1_val as usize;
|
||||||
assert!(!seen[v], "TAB1 maps two inputs to {:#04x}", v);
|
assert!(!seen[v], "TAB1 maps two inputs to {:#04x}", v);
|
||||||
seen[v] = true;
|
seen[v] = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ pub struct DvdTitleSet {
|
|||||||
|
|
||||||
/// A single title (from PGC + TT_SRPT chapter count).
|
/// A single title (from PGC + TT_SRPT chapter count).
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct DvdTitle {
|
pub struct DvdTitle {
|
||||||
/// Number of chapters (PTTs)
|
/// Number of chapters (PTTs)
|
||||||
pub chapters: u16,
|
pub chapters: u16,
|
||||||
@@ -58,6 +59,7 @@ pub struct DvdCell {
|
|||||||
|
|
||||||
/// DVD video stream attributes.
|
/// DVD video stream attributes.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct DvdVideoAttr {
|
pub struct DvdVideoAttr {
|
||||||
pub codec: String,
|
pub codec: String,
|
||||||
pub resolution: String,
|
pub resolution: String,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ use crate::udf::UdfFs;
|
|||||||
|
|
||||||
/// A stream label extracted from disc config files.
|
/// A stream label extracted from disc config files.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct StreamLabel {
|
pub struct StreamLabel {
|
||||||
/// STN index (1-based)
|
/// STN index (1-based)
|
||||||
pub stream_number: u16,
|
pub stream_number: u16,
|
||||||
@@ -45,6 +46,7 @@ pub enum StreamLabelType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub enum LabelPurpose {
|
pub enum LabelPurpose {
|
||||||
Normal,
|
Normal,
|
||||||
Commentary,
|
Commentary,
|
||||||
|
|||||||
@@ -108,9 +108,7 @@ fn parse_token(s: &str) -> Option<StreamLabel> {
|
|||||||
} else if part == "ACOM" {
|
} else if part == "ACOM" {
|
||||||
purpose = LabelPurpose::Commentary;
|
purpose = LabelPurpose::Commentary;
|
||||||
is_audio = true;
|
is_audio = true;
|
||||||
} else if part == "ADLG" {
|
} else if part == "ADLG" || part == "ATRI" {
|
||||||
is_audio = true;
|
|
||||||
} else if part == "ATRI" {
|
|
||||||
is_audio = true;
|
is_audio = true;
|
||||||
} else if part == "SDH" {
|
} else if part == "SDH" {
|
||||||
qualifier = LabelQualifier::Sdh;
|
qualifier = LabelQualifier::Sdh;
|
||||||
@@ -120,9 +118,7 @@ fn parse_token(s: &str) -> Option<StreamLabel> {
|
|||||||
} else if part == "SCOM" {
|
} else if part == "SCOM" {
|
||||||
purpose = LabelPurpose::Commentary;
|
purpose = LabelPurpose::Commentary;
|
||||||
is_subtitle = true;
|
is_subtitle = true;
|
||||||
} else if part == "STRI" {
|
} else if part == "STRI" || part == "TXT" {
|
||||||
is_subtitle = true;
|
|
||||||
} else if part == "TXT" {
|
|
||||||
is_subtitle = true;
|
is_subtitle = true;
|
||||||
} else if part == "FOR" {
|
} else if part == "FOR" {
|
||||||
qualifier = LabelQualifier::Forced;
|
qualifier = LabelQualifier::Forced;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use crate::error::{Error, Result};
|
|||||||
|
|
||||||
/// Parsed MPLS playlist.
|
/// Parsed MPLS playlist.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct Playlist {
|
pub struct Playlist {
|
||||||
/// MPLS version (e.g. "0200" or "0300")
|
/// MPLS version (e.g. "0200" or "0300")
|
||||||
pub version: String,
|
pub version: String,
|
||||||
@@ -23,6 +24,7 @@ pub struct Playlist {
|
|||||||
|
|
||||||
/// A playlist mark entry from the PlayListMark section.
|
/// A playlist mark entry from the PlayListMark section.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct PlaylistMark {
|
pub struct PlaylistMark {
|
||||||
/// Mark type: 1 = chapter entry mark
|
/// Mark type: 1 = chapter entry mark
|
||||||
pub mark_type: u8,
|
pub mark_type: u8,
|
||||||
@@ -34,6 +36,7 @@ pub struct PlaylistMark {
|
|||||||
|
|
||||||
/// A play item — one clip reference with in/out times.
|
/// A play item — one clip reference with in/out times.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct PlayItem {
|
pub struct PlayItem {
|
||||||
/// Clip filename without extension (e.g. "00001")
|
/// Clip filename without extension (e.g. "00001")
|
||||||
pub clip_id: String,
|
pub clip_id: String,
|
||||||
|
|||||||
@@ -101,12 +101,7 @@ impl CodecParser for Ac3Parser {
|
|||||||
|
|
||||||
/// Find AC3/E-AC-3 syncword (0x0B77) in data.
|
/// Find AC3/E-AC-3 syncword (0x0B77) in data.
|
||||||
fn find_ac3_sync(data: &[u8]) -> Option<usize> {
|
fn find_ac3_sync(data: &[u8]) -> Option<usize> {
|
||||||
for i in 0..data.len().saturating_sub(1) {
|
(0..data.len().saturating_sub(1)).find(|&i| data[i] == 0x0B && data[i + 1] == 0x77)
|
||||||
if data[i] == 0x0B && data[i + 1] == 0x77 {
|
|
||||||
return Some(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract bsid from an AC-3/E-AC-3 frame starting at the syncword.
|
/// Extract bsid from an AC-3/E-AC-3 frame starting at the syncword.
|
||||||
|
|||||||
@@ -70,16 +70,12 @@ pub fn find_dts_hd_ext_sync(data: &[u8]) -> Option<usize> {
|
|||||||
if data.len() < 4 {
|
if data.len() < 4 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
for i in 0..=data.len() - 4 {
|
(0..=data.len() - 4).find(|&i| {
|
||||||
if data[i] == DTS_HD_EXT_SYNC[0]
|
data[i] == DTS_HD_EXT_SYNC[0]
|
||||||
&& data[i + 1] == DTS_HD_EXT_SYNC[1]
|
&& data[i + 1] == DTS_HD_EXT_SYNC[1]
|
||||||
&& data[i + 2] == DTS_HD_EXT_SYNC[2]
|
&& data[i + 2] == DTS_HD_EXT_SYNC[2]
|
||||||
&& data[i + 3] == DTS_HD_EXT_SYNC[3]
|
&& data[i + 3] == DTS_HD_EXT_SYNC[3]
|
||||||
{
|
})
|
||||||
return Some(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate DTS-HD extension frame size from the extension header.
|
/// Calculate DTS-HD extension frame size from the extension header.
|
||||||
|
|||||||
+11
-15
@@ -110,15 +110,16 @@ impl CodecParser for H264Parser {
|
|||||||
// pictureParameterSetLength = pps.len()
|
// pictureParameterSetLength = pps.len()
|
||||||
// pictureParameterSetNALUnit = pps
|
// pictureParameterSetNALUnit = pps
|
||||||
|
|
||||||
let mut record = Vec::new();
|
let mut record = vec![
|
||||||
record.push(1); // configurationVersion
|
1, // configurationVersion
|
||||||
record.push(sps[1]); // profile
|
sps[1], // profile
|
||||||
record.push(sps[2]); // compatibility
|
sps[2], // compatibility
|
||||||
record.push(sps[3]); // level
|
sps[3], // level
|
||||||
record.push(0xFF); // 6 bits reserved (111111) + 2 bits lengthSizeMinusOne (11 = 3)
|
0xFF, // 6 bits reserved (111111) + 2 bits lengthSizeMinusOne (11 = 3)
|
||||||
record.push(0xE1); // 3 bits reserved (111) + 5 bits numSPS (1)
|
0xE1, // 3 bits reserved (111) + 5 bits numSPS (1)
|
||||||
record.push((sps.len() >> 8) as u8);
|
(sps.len() >> 8) as u8,
|
||||||
record.push(sps.len() as u8);
|
sps.len() as u8,
|
||||||
|
];
|
||||||
record.extend_from_slice(sps);
|
record.extend_from_slice(sps);
|
||||||
record.push(1); // numPPS
|
record.push(1); // numPPS
|
||||||
record.push((pps.len() >> 8) as u8);
|
record.push((pps.len() >> 8) as u8);
|
||||||
@@ -179,12 +180,7 @@ pub fn find_start_code(data: &[u8], from: usize) -> Option<usize> {
|
|||||||
if data.len() < from + 3 {
|
if data.len() < from + 3 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
for i in from..data.len() - 2 {
|
(from..data.len() - 2).find(|&i| data[i] == 0x00 && data[i + 1] == 0x00 && data[i + 2] == 0x01)
|
||||||
if data[i] == 0x00 && data[i + 1] == 0x00 && data[i + 2] == 0x01 {
|
|
||||||
return Some(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Skip past the start code at position `pos`, returning the first byte after it.
|
/// Skip past the start code at position `pos`, returning the first byte after it.
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ mod tests {
|
|||||||
fn header_skip_extracts_pcm_data() {
|
fn header_skip_extracts_pcm_data() {
|
||||||
let mut parser = LpcmParser::new();
|
let mut parser = LpcmParser::new();
|
||||||
// 4-byte LPCM header + 6 bytes of PCM data
|
// 4-byte LPCM header + 6 bytes of PCM data
|
||||||
let header = vec![0x00, 0x01, 0x00, 0b10_01_0001]; // frame#=1, quant=24bit, rate=48k, ch=1
|
let header = vec![0x00, 0x01, 0x00, 0b1001_0001]; // frame#=1, quant=24bit, rate=48k, ch=1
|
||||||
let pcm_data = vec![0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE];
|
let pcm_data = vec![0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE];
|
||||||
let mut pes_data = header;
|
let mut pes_data = header;
|
||||||
pes_data.extend_from_slice(&pcm_data);
|
pes_data.extend_from_slice(&pcm_data);
|
||||||
|
|||||||
@@ -195,12 +195,7 @@ fn find_start_code(data: &[u8], from: usize) -> Option<usize> {
|
|||||||
if data.len() < from + 3 {
|
if data.len() < from + 3 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
for i in from..data.len() - 2 {
|
(from..data.len() - 2).find(|&i| data[i] == 0x00 && data[i + 1] == 0x00 && data[i + 2] == 0x01)
|
||||||
if data[i] == 0x00 && data[i + 1] == 0x00 && data[i + 2] == 0x01 {
|
|
||||||
return Some(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -122,12 +122,7 @@ impl CodecParser for Vc1Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn find_next_sc(data: &[u8], from: usize) -> Option<usize> {
|
fn find_next_sc(data: &[u8], from: usize) -> Option<usize> {
|
||||||
for i in from..data.len().saturating_sub(2) {
|
(from..data.len().saturating_sub(2)).find(|&i| data[i] == 0x00 && data[i + 1] == 0x00 && data[i + 2] == 0x01)
|
||||||
if data[i] == 0x00 && data[i + 1] == 0x00 && data[i + 2] == 0x01 {
|
|
||||||
return Some(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
+3
-3
@@ -359,7 +359,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn state_advances_across_extents() {
|
fn state_advances_across_extents() {
|
||||||
// Simulate two extents of 6 sectors each (2 aligned units each).
|
// Simulate two extents of 6 sectors each (2 aligned units each).
|
||||||
let extents = vec![
|
let extents = [
|
||||||
Extent {
|
Extent {
|
||||||
start_lba: 100,
|
start_lba: 100,
|
||||||
sector_count: 6,
|
sector_count: 6,
|
||||||
@@ -406,7 +406,7 @@ mod tests {
|
|||||||
/// (moved past) rather than causing an infinite loop.
|
/// (moved past) rather than causing an infinite loop.
|
||||||
#[test]
|
#[test]
|
||||||
fn unaligned_extent_is_skipped() {
|
fn unaligned_extent_is_skipped() {
|
||||||
let extents = vec![
|
let extents = [
|
||||||
Extent {
|
Extent {
|
||||||
start_lba: 50,
|
start_lba: 50,
|
||||||
sector_count: 2, // < 3, cannot form an aligned unit
|
sector_count: 2, // < 3, cannot form an aligned unit
|
||||||
@@ -449,7 +449,7 @@ mod tests {
|
|||||||
/// Verify that multiple reads from the same extent produce advancing offsets.
|
/// Verify that multiple reads from the same extent produce advancing offsets.
|
||||||
#[test]
|
#[test]
|
||||||
fn multiple_batches_within_one_extent() {
|
fn multiple_batches_within_one_extent() {
|
||||||
let extents = vec![Extent {
|
let extents = [Extent {
|
||||||
start_lba: 1000,
|
start_lba: 1000,
|
||||||
sector_count: 18, // 6 aligned units = 3 batches of 6 sectors
|
sector_count: 18, // 6 aligned units = 3 batches of 6 sectors
|
||||||
}];
|
}];
|
||||||
|
|||||||
+2
-2
@@ -558,7 +558,7 @@ mod tests {
|
|||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
write_uint(&mut buf, test_id, val).unwrap();
|
write_uint(&mut buf, test_id, val).unwrap();
|
||||||
let mut cursor = Cursor::new(&buf);
|
let mut cursor = Cursor::new(&buf);
|
||||||
let (id, id_len) = read_id(&mut cursor).unwrap();
|
let (id, _id_len) = read_id(&mut cursor).unwrap();
|
||||||
assert_eq!(id, test_id);
|
assert_eq!(id, test_id);
|
||||||
let (size, _) = read_size(&mut cursor).unwrap();
|
let (size, _) = read_size(&mut cursor).unwrap();
|
||||||
let read_val = read_uint_val(&mut cursor, size as usize).unwrap();
|
let read_val = read_uint_val(&mut cursor, size as usize).unwrap();
|
||||||
@@ -594,7 +594,7 @@ mod tests {
|
|||||||
0.0,
|
0.0,
|
||||||
1.0,
|
1.0,
|
||||||
-1.0,
|
-1.0,
|
||||||
3.14159265358979,
|
std::f64::consts::PI,
|
||||||
48000.0,
|
48000.0,
|
||||||
7200000.0,
|
7200000.0,
|
||||||
f64::MIN,
|
f64::MIN,
|
||||||
|
|||||||
@@ -490,6 +490,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Read a little-endian u32 from a byte slice at the given offset.
|
/// Read a little-endian u32 from a byte slice at the given offset.
|
||||||
|
#[allow(dead_code)]
|
||||||
fn le_u32(data: &[u8], off: usize) -> u32 {
|
fn le_u32(data: &[u8], off: usize) -> u32 {
|
||||||
u32::from_le_bytes([data[off], data[off + 1], data[off + 2], data[off + 3]])
|
u32::from_le_bytes([data[off], data[off + 1], data[off + 2], data[off + 3]])
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -737,7 +737,7 @@ mod tests {
|
|||||||
// (MKV default is 1). When is_default is false, FlagDefault=0 IS written.
|
// (MKV default is 1). When is_default is false, FlagDefault=0 IS written.
|
||||||
// So we should find at least one FlagDefault element (for the non-default track).
|
// So we should find at least one FlagDefault element (for the non-default track).
|
||||||
let flag_default_id = ebml::FLAG_DEFAULT.to_be_bytes();
|
let flag_default_id = ebml::FLAG_DEFAULT.to_be_bytes();
|
||||||
let needle = &[flag_default_id[3]]; // 0x88 is a 1-byte ID
|
let _needle = &[flag_default_id[3]]; // 0x88 is a 1-byte ID
|
||||||
let count = data.windows(1).filter(|w| w[0] == 0x88).count();
|
let count = data.windows(1).filter(|w| w[0] == 0x88).count();
|
||||||
// 0x88 appears as FlagDefault + as TrackType (also 0x83... no, 0x83 != 0x88)
|
// 0x88 appears as FlagDefault + as TrackType (also 0x83... no, 0x83 != 0x88)
|
||||||
// FlagDefault (0x88) should appear for the non-default track
|
// FlagDefault (0x88) should appear for the non-default track
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ struct ReadState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum Mode {
|
enum Mode {
|
||||||
Write(WriteState),
|
Write(Box<WriteState>),
|
||||||
Read(ReadState),
|
Read(ReadState),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ impl MkvStream {
|
|||||||
pub fn new(writer: impl Write + Seek + 'static) -> Self {
|
pub fn new(writer: impl Write + Seek + 'static) -> Self {
|
||||||
Self {
|
Self {
|
||||||
disc_title: DiscTitle::empty(),
|
disc_title: DiscTitle::empty(),
|
||||||
mode: Mode::Write(WriteState {
|
mode: Mode::Write(Box::new(WriteState {
|
||||||
demuxer: TsDemuxer::new(&[]),
|
demuxer: TsDemuxer::new(&[]),
|
||||||
muxer: None,
|
muxer: None,
|
||||||
writer: Some(Box::new(writer)),
|
writer: Some(Box::new(writer)),
|
||||||
@@ -70,7 +70,7 @@ impl MkvStream {
|
|||||||
lookahead: LookaheadBuffer::new(DEFAULT_MAX_BUFFER),
|
lookahead: LookaheadBuffer::new(DEFAULT_MAX_BUFFER),
|
||||||
phase: WritePhase::Scanning,
|
phase: WritePhase::Scanning,
|
||||||
video_pending: 0,
|
video_pending: 0,
|
||||||
}),
|
})),
|
||||||
max_buffer: DEFAULT_MAX_BUFFER,
|
max_buffer: DEFAULT_MAX_BUFFER,
|
||||||
finished: false,
|
finished: false,
|
||||||
file_size: None,
|
file_size: None,
|
||||||
@@ -607,8 +607,8 @@ fn frame_to_ts(out: &mut Vec<u8>, track: u16, pts_ms: i64, data: &[u8]) {
|
|||||||
if pad > 1 {
|
if pad > 1 {
|
||||||
pkt[9] = 0x00;
|
pkt[9] = 0x00;
|
||||||
}
|
}
|
||||||
for i in 10..(8 + pad).min(192) {
|
for byte in pkt.iter_mut().take((8 + pad).min(192)).skip(10) {
|
||||||
pkt[i] = 0xFF;
|
*byte = 0xFF;
|
||||||
}
|
}
|
||||||
pkt[8 + pad..8 + pad + n].copy_from_slice(&pes[off..off + n]);
|
pkt[8 + pad..8 + pad + n].copy_from_slice(&pes[off..off + n]);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+2
-12
@@ -81,12 +81,7 @@ impl PsDemuxer {
|
|||||||
let mut packets = Vec::with_capacity(4);
|
let mut packets = Vec::with_capacity(4);
|
||||||
let mut pos = 0;
|
let mut pos = 0;
|
||||||
|
|
||||||
loop {
|
while let Some(sc) = find_start_code(&self.buffer, pos) {
|
||||||
// Find the next start code.
|
|
||||||
let sc = match find_start_code(&self.buffer, pos) {
|
|
||||||
Some(p) => p,
|
|
||||||
None => break,
|
|
||||||
};
|
|
||||||
|
|
||||||
if sc + 3 >= self.buffer.len() {
|
if sc + 3 >= self.buffer.len() {
|
||||||
// Not enough bytes to read the start code ID.
|
// Not enough bytes to read the start code ID.
|
||||||
@@ -275,12 +270,7 @@ fn find_start_code(data: &[u8], from: usize) -> Option<usize> {
|
|||||||
if data.len() < from + 3 {
|
if data.len() < from + 3 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
for i in from..data.len() - 2 {
|
(from..data.len() - 2).find(|&i| data[i] == 0x00 && data[i + 1] == 0x00 && data[i + 2] == 0x01)
|
||||||
if data[i] == 0x00 && data[i + 1] == 0x00 && data[i + 2] == 0x01 {
|
|
||||||
return Some(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
+4
-5
@@ -125,17 +125,16 @@ impl TsDemuxer {
|
|||||||
let mut completed = Vec::with_capacity(4);
|
let mut completed = Vec::with_capacity(4);
|
||||||
|
|
||||||
// Prepend any remainder from previous call
|
// Prepend any remainder from previous call
|
||||||
let work: &[u8];
|
|
||||||
let mut combined: Vec<u8> = Vec::new();
|
let mut combined: Vec<u8> = Vec::new();
|
||||||
if !self.remainder.is_empty() {
|
let work: &[u8] = if !self.remainder.is_empty() {
|
||||||
combined.reserve(self.remainder.len() + data.len());
|
combined.reserve(self.remainder.len() + data.len());
|
||||||
combined.extend_from_slice(&self.remainder);
|
combined.extend_from_slice(&self.remainder);
|
||||||
combined.extend_from_slice(data);
|
combined.extend_from_slice(data);
|
||||||
self.remainder.clear();
|
self.remainder.clear();
|
||||||
work = &combined;
|
&combined
|
||||||
} else {
|
} else {
|
||||||
work = data;
|
data
|
||||||
}
|
};
|
||||||
|
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -513,6 +513,7 @@ pub fn read_filesystem(reader: &mut dyn SectorReader) -> Result<UdfFs> {
|
|||||||
/// Each directory is an ICB (Extended File Entry) pointing to directory data
|
/// Each directory is an ICB (Extended File Entry) pointing to directory data
|
||||||
/// containing File Identifier Descriptors (FIDs). Each FID names a file/subdir
|
/// containing File Identifier Descriptors (FIDs). Each FID names a file/subdir
|
||||||
/// and points to its ICB.
|
/// and points to its ICB.
|
||||||
|
#[allow(clippy::only_used_in_recursion)]
|
||||||
fn read_directory(
|
fn read_directory(
|
||||||
reader: &mut dyn SectorReader,
|
reader: &mut dyn SectorReader,
|
||||||
part_start: u32,
|
part_start: u32,
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ fn css_descramble_sector_roundtrip_via_public_api() {
|
|||||||
sector[0x82] = 0x01;
|
sector[0x82] = 0x01;
|
||||||
sector[0x83] = 0xE0;
|
sector[0x83] = 0xE0;
|
||||||
// Fill content
|
// Fill content
|
||||||
for i in 0x84..2048 {
|
for (i, byte) in sector.iter_mut().enumerate().take(2048).skip(0x84) {
|
||||||
sector[i] = (i & 0xFF) as u8;
|
*byte = (i & 0xFF) as u8;
|
||||||
}
|
}
|
||||||
let original = sector.clone();
|
let original = sector.clone();
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -265,7 +265,7 @@ fn make_dir_icb(data_meta_lba: u32, data_len: u32) -> Vec<u8> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn make_parent_fid() -> Vec<u8> {
|
fn make_parent_fid() -> Vec<u8> {
|
||||||
let fid_len = ((38 + 0 + 0 + 3) & !3) as usize;
|
let fid_len = (38 + 3) & !3;
|
||||||
let mut fid = vec![0u8; fid_len];
|
let mut fid = vec![0u8; fid_len];
|
||||||
fid[0..2].copy_from_slice(&257u16.to_le_bytes());
|
fid[0..2].copy_from_slice(&257u16.to_le_bytes());
|
||||||
fid[18] = 0x08;
|
fid[18] = 0x08;
|
||||||
@@ -278,7 +278,7 @@ fn make_fid(name: &str, icb_meta_lba: u32, is_dir: bool) -> Vec<u8> {
|
|||||||
name_bytes.extend_from_slice(name.as_bytes());
|
name_bytes.extend_from_slice(name.as_bytes());
|
||||||
let l_fi = name_bytes.len() as u8;
|
let l_fi = name_bytes.len() as u8;
|
||||||
let file_chars: u8 = if is_dir { 0x02 } else { 0x00 };
|
let file_chars: u8 = if is_dir { 0x02 } else { 0x00 };
|
||||||
let fid_len = ((38 + 0 + l_fi as usize + 3) & !3) as usize;
|
let fid_len = (38 + l_fi as usize + 3) & !3;
|
||||||
let mut fid = vec![0u8; fid_len];
|
let mut fid = vec![0u8; fid_len];
|
||||||
fid[0..2].copy_from_slice(&257u16.to_le_bytes());
|
fid[0..2].copy_from_slice(&257u16.to_le_bytes());
|
||||||
fid[18] = file_chars;
|
fid[18] = file_chars;
|
||||||
|
|||||||
+3
-3
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use libfreemkv::mux::meta::M2tsMeta;
|
use libfreemkv::mux::meta::M2tsMeta;
|
||||||
use libfreemkv::*;
|
use libfreemkv::*;
|
||||||
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
|
use std::io::{Cursor, Read, Write};
|
||||||
|
|
||||||
fn sample_disc_title() -> DiscTitle {
|
fn sample_disc_title() -> DiscTitle {
|
||||||
DiscTitle {
|
DiscTitle {
|
||||||
@@ -325,8 +325,8 @@ fn m2ts_passthrough_preserves_data() {
|
|||||||
pkt[4] = 0x47;
|
pkt[4] = 0x47;
|
||||||
pkt[5] = (i % 3) << 4;
|
pkt[5] = (i % 3) << 4;
|
||||||
pkt[6] = i;
|
pkt[6] = i;
|
||||||
for j in 8..192 {
|
for (j, byte) in pkt.iter_mut().enumerate().skip(8) {
|
||||||
pkt[j] = i.wrapping_add(j as u8);
|
*byte = i.wrapping_add(j as u8);
|
||||||
}
|
}
|
||||||
original.extend_from_slice(&pkt);
|
original.extend_from_slice(&pkt);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -154,7 +154,7 @@ fn make_fid(name: &str, icb_meta_lba: u32, is_dir: bool) -> Vec<u8> {
|
|||||||
let file_chars: u8 = if is_dir { 0x02 } else { 0x00 };
|
let file_chars: u8 = if is_dir { 0x02 } else { 0x00 };
|
||||||
|
|
||||||
// Fixed header = 38 bytes, L_IU = 0
|
// Fixed header = 38 bytes, L_IU = 0
|
||||||
let fid_len = ((38 + 0 + l_fi as usize + 3) & !3) as usize; // 4-byte aligned
|
let fid_len = (38 + l_fi as usize + 3) & !3; // 4-byte aligned
|
||||||
let mut fid = vec![0u8; fid_len];
|
let mut fid = vec![0u8; fid_len];
|
||||||
// tag_id = 257
|
// tag_id = 257
|
||||||
fid[0..2].copy_from_slice(&257u16.to_le_bytes());
|
fid[0..2].copy_from_slice(&257u16.to_le_bytes());
|
||||||
@@ -176,7 +176,7 @@ fn make_fid(name: &str, icb_meta_lba: u32, is_dir: bool) -> Vec<u8> {
|
|||||||
|
|
||||||
/// Build a parent FID (file_chars = 0x08, no name).
|
/// Build a parent FID (file_chars = 0x08, no name).
|
||||||
fn make_parent_fid() -> Vec<u8> {
|
fn make_parent_fid() -> Vec<u8> {
|
||||||
let fid_len = ((38 + 0 + 0 + 3) & !3) as usize;
|
let fid_len = (38 + 3) & !3;
|
||||||
let mut fid = vec![0u8; fid_len];
|
let mut fid = vec![0u8; fid_len];
|
||||||
fid[0..2].copy_from_slice(&257u16.to_le_bytes());
|
fid[0..2].copy_from_slice(&257u16.to_le_bytes());
|
||||||
fid[18] = 0x08; // parent
|
fid[18] = 0x08; // parent
|
||||||
@@ -362,7 +362,7 @@ fn read_filesystem_with_subdirectory() {
|
|||||||
reader.set_sector(35, make_terminator());
|
reader.set_sector(35, make_terminator());
|
||||||
|
|
||||||
// FSD -> root ICB at meta LBA 1
|
// FSD -> root ICB at meta LBA 1
|
||||||
reader.set_sector(partition_start + 0, make_fsd_sector(1));
|
reader.set_sector(partition_start, make_fsd_sector(1));
|
||||||
|
|
||||||
// Root dir: parent FID + BDMV dir FID
|
// Root dir: parent FID + BDMV dir FID
|
||||||
let parent_fid = make_parent_fid();
|
let parent_fid = make_parent_fid();
|
||||||
@@ -419,7 +419,7 @@ fn find_dir_case_insensitive() {
|
|||||||
reader.set_sector(35, make_terminator());
|
reader.set_sector(35, make_terminator());
|
||||||
|
|
||||||
// FSD
|
// FSD
|
||||||
reader.set_sector(partition_start + 0, make_fsd_sector(1));
|
reader.set_sector(partition_start, make_fsd_sector(1));
|
||||||
|
|
||||||
// Root -> BDMV
|
// Root -> BDMV
|
||||||
let root_data = [make_parent_fid(), make_fid("BDMV", 3, true)].concat();
|
let root_data = [make_parent_fid(), make_fid("BDMV", 3, true)].concat();
|
||||||
|
|||||||
Reference in New Issue
Block a user