From e68d3240580cecdcd401c11d1fc65d47cd3ac339 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Sat, 25 Apr 2026 18:20:18 +0200 Subject: [PATCH] rawvideo{enc,dec}: support 1-4 bit paletted formats --- nihav-commonfmt/src/codecs/rawvideo.rs | 38 ++++++++++- nihav-commonfmt/src/codecs/rawvideoenc.rs | 83 ++++++++++++++++++++--- 2 files changed, 112 insertions(+), 9 deletions(-) diff --git a/nihav-commonfmt/src/codecs/rawvideo.rs b/nihav-commonfmt/src/codecs/rawvideo.rs index dd4a031..79b9f0d 100644 --- a/nihav-commonfmt/src/codecs/rawvideo.rs +++ b/nihav-commonfmt/src/codecs/rawvideo.rs @@ -71,7 +71,43 @@ impl NADecoder for RawDecoder { let strides = vec![stride]; NABufferType::VideoPacked(NAVideoBuffer::from_raw_parts(*vinfo, src, offs, strides).into_ref()) } else { - let mut buf = src.clone(); + let mut buf = match vinfo.bits.min(8) { + 1 => { + let mut buf = Vec::with_capacity(width * height + 768); + for line in src.chunks_exact(width).take(height) { + for &oct in line.iter() { + for i in (0..8).rev() { + buf.push((oct >> i) & 1); + } + } + } + NABufferRef::new(buf) + }, + 2 => { + let mut buf = Vec::with_capacity(width * height + 768); + for line in src.chunks_exact(width).take(height) { + for &quad in line.iter() { + buf.push( quad >> 6); + buf.push((quad >> 4) & 0x3); + buf.push((quad >> 2) & 0x3); + buf.push( quad & 0x3); + } + } + NABufferRef::new(buf) + }, + 4 => { + let mut buf = Vec::with_capacity(width * height + 768); + for line in src.chunks_exact(width).take(height) { + for &pair in line.iter() { + buf.push(pair >> 4); + buf.push(pair & 0xF); + } + } + NABufferRef::new(buf) + }, + 8 => NABufferRef::new(Vec::clone(&src)), + _ => return Err(DecoderError::NotImplemented), + }; let offs = vec![0, buf.len()]; let strides = vec![width, 0]; let mut found = false; diff --git a/nihav-commonfmt/src/codecs/rawvideoenc.rs b/nihav-commonfmt/src/codecs/rawvideoenc.rs index ec003b0..6789c41 100644 --- a/nihav-commonfmt/src/codecs/rawvideoenc.rs +++ b/nihav-commonfmt/src/codecs/rawvideoenc.rs @@ -69,14 +69,81 @@ impl NAEncoder for RawEncoder { let sstride = vbuf.get_stride(0); let dstride = width; dbuf = Vec::with_capacity(dstride * height); - if !vinfo.flipped { - for line in src.chunks(sstride).take(height) { - dbuf.extend_from_slice(&line[..dstride]); - } - } else { - for line in src.chunks(sstride).take(height).rev() { - dbuf.extend_from_slice(&line[..dstride]); - } + match vinfo.bits.min(8) { + 8 => { + if !vinfo.flipped { + for line in src.chunks(sstride).take(height) { + dbuf.extend_from_slice(&line[..dstride]); + } + } else { + for line in src.chunks(sstride).take(height).rev() { + dbuf.extend_from_slice(&line[..dstride]); + } + } + }, + 4 => { + if (vinfo.width & 1) != 0 { + return Err(EncoderError::NotImplemented); + } + if !vinfo.flipped { + for line in src.chunks(sstride).take(height) { + for ppair in line.chunks_exact(2) { + dbuf.push((ppair[0] << 4) | ppair[1]); + } + } + } else { + for line in src.chunks(sstride).take(height).rev() { + for ppair in line.chunks_exact(2) { + dbuf.push((ppair[0] << 4) | ppair[1]); + } + } + } + }, + 2 => { + if (vinfo.width & 3) != 0 { + return Err(EncoderError::NotImplemented); + } + if !vinfo.flipped { + for line in src.chunks(sstride).take(height) { + for quad in line.chunks_exact(4) { + dbuf.push((quad[0] << 6) | (quad[1] << 4) | (quad[2] << 2) | quad[3]); + } + } + } else { + for line in src.chunks(sstride).take(height).rev() { + for quad in line.chunks_exact(4) { + dbuf.push((quad[0] << 6) | (quad[1] << 4) | (quad[2] << 2) | quad[3]); + } + } + } + }, + 1 => { + if (vinfo.width & 8) != 0 { + return Err(EncoderError::NotImplemented); + } + if !vinfo.flipped { + for line in src.chunks(sstride).take(height) { + for oct in line.chunks_exact(8) { + let mut bb = 0; + for &b in oct.iter() { + bb = bb * 2 + b; + } + dbuf.push(bb); + } + } + } else { + for line in src.chunks(sstride).take(height).rev() { + for oct in line.chunks_exact(8) { + let mut bb = 0; + for &b in oct.iter() { + bb = bb * 2 + b; + } + dbuf.push(bb); + } + } + } + }, + _ => return Err(EncoderError::NotImplemented), } let mut pkt = NAPacket::new(self.stream.clone().unwrap(), frm.ts, true, dbuf); let mut npal = [0; 1024]; -- 2.39.5