From d59f3a01d364fa951c6986f54944f3a36ee1492f Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Mon, 9 Feb 2026 18:16:06 +0100 Subject: [PATCH] pgvv: support interlaced mode --- nihav-misc/src/codecs/pgvv.rs | 37 ++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/nihav-misc/src/codecs/pgvv.rs b/nihav-misc/src/codecs/pgvv.rs index 1ddba9c..35d80cf 100644 --- a/nihav-misc/src/codecs/pgvv.rs +++ b/nihav-misc/src/codecs/pgvv.rs @@ -141,6 +141,7 @@ struct RadiusStudioDecoder { codebook: [[Option>; 4]; 2], width: usize, height: usize, + ilaced: bool, } fn read_dc(br: &mut BitReader, cb: &Codebook) -> DecoderResult { @@ -210,11 +211,12 @@ impl RadiusStudioDecoder { codebook: [[None, None, None, None], [None, None, None, None]], width: 0, height: 0, + ilaced: false, } } #[allow(clippy::needless_range_loop)] - fn decode_scan(&mut self, src: &[u8], mut buf: NAVideoBufferRef, ci: &[ComponentInfo], ss: usize, se: usize) -> DecoderResult { + fn decode_scan(&mut self, src: &[u8], mut buf: NAVideoBufferRef, ci: &[ComponentInfo], ss: usize, se: usize, field2: bool) -> DecoderResult { let num_components = ci.len(); let mut last_dc = [1024; MAX_CHROMATONS]; let mut dc_cbs = Vec::with_capacity(num_components); @@ -251,7 +253,17 @@ impl RadiusStudioDecoder { } let mut blocks; - for _y in (0..self.height).step_by(vstep) { + let height = if !self.ilaced { self.height } else { self.height / 2 }; + let mut stride = frm.stride; + if self.ilaced { + for (strd, off) in stride.iter_mut().zip(offs.iter_mut()) { + if field2 { + *off += *strd; + } + *strd <<= 1; + } + } + for _y in (0..height).step_by(vstep) { for x in 0..(self.width + hstep - 1) / hstep { for i in 0..num_components { blocks = [[0; 64]; 4]; @@ -268,19 +280,19 @@ impl RadiusStudioDecoder { } match self.subsamp[i] { 0x11 => { - put_block(&blocks[0], &mut frm.data[offs[i] + x * 8..], frm.stride[i]); + put_block(&blocks[0], &mut frm.data[offs[i] + x * 8..], stride[i]); }, 0x21 => { - put_block(&blocks[0], &mut frm.data[offs[i] + x * 16..], frm.stride[i]); - put_block(&blocks[1], &mut frm.data[offs[i] + x * 16 + 8..], frm.stride[i]); + put_block(&blocks[0], &mut frm.data[offs[i] + x * 16..], stride[i]); + put_block(&blocks[1], &mut frm.data[offs[i] + x * 16 + 8..], stride[i]); }, 0x12 => { - put_block(&blocks[0], &mut frm.data[offs[i] + x * 8..], frm.stride[i]); - put_block(&blocks[1], &mut frm.data[offs[i] + x * 8 + frm.stride[i] * 8..], frm.stride[i]); + put_block(&blocks[0], &mut frm.data[offs[i] + x * 8..], stride[i]); + put_block(&blocks[1], &mut frm.data[offs[i] + x * 8 + stride[i] * 8..], stride[i]); }, 0x22 => { for j in 0..4 { - put_block(&blocks[j], &mut frm.data[offs[i] + x * 16 + (j & 1) * 8 + (j >> 1) * 8 * frm.stride[i]..], frm.stride[i]); + put_block(&blocks[j], &mut frm.data[offs[i] + x * 16 + (j & 1) * 8 + (j >> 1) * 8 * stride[i]..], stride[i]); } }, _ => unreachable!(), @@ -288,7 +300,7 @@ impl RadiusStudioDecoder { } } for i in 0..num_components { - offs[i] += frm.stride[i] * ystep[i]; + offs[i] += stride[i] * ystep[i]; } } @@ -367,7 +379,7 @@ impl NADecoder for RadiusStudioDecoder { let _size_v0 = br.read_u32be()? as usize; let field2_size = br.read_u32be()? as usize; if field2_size != 0 { - return Err(DecoderError::NotImplemented); + self.ilaced = true; } let version = br.read_u16be()?; validate!(version <= 2); @@ -459,7 +471,10 @@ impl NADecoder for RadiusStudioDecoder { ComponentInfo { component_id: 2, dc_table_id: 1, ac_table_id: 1 }, ComponentInfo { component_id: 3, dc_table_id: 1, ac_table_id: 1 }, ]; - self.decode_scan(&src[hdr_size..], buf, &ci, 0, 63)?; + self.decode_scan(&src[hdr_size..], buf.clone(), &ci, 0, 63, false)?; + if self.ilaced { + self.decode_scan(&src[hdr_size..], buf, &ci, 0, 63, true)?; + } } else { unreachable!(); } let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo); -- 2.39.5