From 3cd64e4f5779f30321ae894b691fa1a7a3a9e6a6 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Sat, 7 Mar 2026 14:06:36 +0100 Subject: [PATCH] h264: split decoder into common and 8-bit specific decoding parts This is a preparation for future high-bitdepth support. --- .../src/codecs/h264/{ => baseline}/cabac.rs | 7 +- .../src/codecs/h264/{ => baseline}/cavlc.rs | 4 +- .../codecs/h264/{ => baseline}/decoder_mt.rs | 1 + .../codecs/h264/{ => baseline}/decoder_st.rs | 1 + .../codecs/h264/{ => baseline}/dispatch.rs | 3 +- .../h264/{ => baseline}/dsp/mc/debug.rs | 0 .../codecs/h264/{ => baseline}/dsp/mc/mod.rs | 0 .../h264/{ => baseline}/dsp/mc/release.rs | 0 .../{ => baseline}/dsp/mc/x86/blockdsp.rs | 0 .../{ => baseline}/dsp/mc/x86/chroma_mc.rs | 0 .../h264/{ => baseline}/dsp/mc/x86/luma_mc.rs | 0 .../h264/{ => baseline}/dsp/mc/x86/mod.rs | 0 .../src/codecs/h264/{ => baseline}/dsp/mod.rs | 0 .../codecs/h264/{ => baseline}/loopfilter.rs | 0 .../codecs/h264/{ => baseline}/mb_recon.rs | 5 +- nihav-itu/src/codecs/h264/baseline/mod.rs | 30 ++ .../src/codecs/h264/{ => baseline}/pic_ref.rs | 5 +- .../src/codecs/h264/{ => baseline}/types.rs | 417 +----------------- nihav-itu/src/codecs/h264/common_types.rs | 417 ++++++++++++++++++ nihav-itu/src/codecs/h264/mod.rs | 70 +-- 20 files changed, 490 insertions(+), 470 deletions(-) rename nihav-itu/src/codecs/h264/{ => baseline}/cabac.rs (99%) rename nihav-itu/src/codecs/h264/{ => baseline}/cavlc.rs (99%) rename nihav-itu/src/codecs/h264/{ => baseline}/decoder_mt.rs (99%) rename nihav-itu/src/codecs/h264/{ => baseline}/decoder_st.rs (99%) rename nihav-itu/src/codecs/h264/{ => baseline}/dispatch.rs (99%) rename nihav-itu/src/codecs/h264/{ => baseline}/dsp/mc/debug.rs (100%) rename nihav-itu/src/codecs/h264/{ => baseline}/dsp/mc/mod.rs (100%) rename nihav-itu/src/codecs/h264/{ => baseline}/dsp/mc/release.rs (100%) rename nihav-itu/src/codecs/h264/{ => baseline}/dsp/mc/x86/blockdsp.rs (100%) rename nihav-itu/src/codecs/h264/{ => baseline}/dsp/mc/x86/chroma_mc.rs (100%) rename nihav-itu/src/codecs/h264/{ => baseline}/dsp/mc/x86/luma_mc.rs (100%) rename nihav-itu/src/codecs/h264/{ => baseline}/dsp/mc/x86/mod.rs (100%) rename nihav-itu/src/codecs/h264/{ => baseline}/dsp/mod.rs (100%) rename nihav-itu/src/codecs/h264/{ => baseline}/loopfilter.rs (100%) rename nihav-itu/src/codecs/h264/{ => baseline}/mb_recon.rs (99%) create mode 100644 nihav-itu/src/codecs/h264/baseline/mod.rs rename nihav-itu/src/codecs/h264/{ => baseline}/pic_ref.rs (99%) rename nihav-itu/src/codecs/h264/{ => baseline}/types.rs (68%) create mode 100644 nihav-itu/src/codecs/h264/common_types.rs diff --git a/nihav-itu/src/codecs/h264/cabac.rs b/nihav-itu/src/codecs/h264/baseline/cabac.rs similarity index 99% rename from nihav-itu/src/codecs/h264/cabac.rs rename to nihav-itu/src/codecs/h264/baseline/cabac.rs index ac93982..1fa122c 100644 --- a/nihav-itu/src/codecs/h264/cabac.rs +++ b/nihav-itu/src/codecs/h264/baseline/cabac.rs @@ -1,9 +1,12 @@ //use nihav_core::codecs::{DecoderResult, DecoderError}; +use nihav_codec_support::codecs::MV; + +use super::super::*; use super::*; -use super::cabac_coder::*; +use super::super::cabac_coder::*; use super::dsp::{CHROMA_DC_SCAN, ZIGZAG, ZIGZAG1, ZIGZAG8X8}; -use super::slice::SliceHeader; +use super::super::slice::SliceHeader; pub fn cabac_decode_mbskip(cabac: &mut CABAC, sstate: &SliceState, slice_hdr: &SliceHeader) -> bool { let skip_idx = if slice_hdr.slice_type.is_p() { 11 } else { 24 }; diff --git a/nihav-itu/src/codecs/h264/cavlc.rs b/nihav-itu/src/codecs/h264/baseline/cavlc.rs similarity index 99% rename from nihav-itu/src/codecs/h264/cavlc.rs rename to nihav-itu/src/codecs/h264/baseline/cavlc.rs index af98aa5..8d9b299 100644 --- a/nihav-itu/src/codecs/h264/cavlc.rs +++ b/nihav-itu/src/codecs/h264/baseline/cavlc.rs @@ -1,10 +1,12 @@ use nihav_core::codecs::{DecoderResult, DecoderError}; +use nihav_codec_support::codecs::MV; use nihav_core::io::bitreader::*; use nihav_core::io::codebook::*; use nihav_core::io::intcode::*; +use super::super::*; use super::*; use super::dsp::{CHROMA_DC_SCAN, ZIGZAG, ZIGZAG1}; -use super::slice::SliceHeader; +use super::super::slice::SliceHeader; fn map_i_type(idx: usize) -> MBType { if idx == 0 { diff --git a/nihav-itu/src/codecs/h264/decoder_mt.rs b/nihav-itu/src/codecs/h264/baseline/decoder_mt.rs similarity index 99% rename from nihav-itu/src/codecs/h264/decoder_mt.rs rename to nihav-itu/src/codecs/h264/baseline/decoder_mt.rs index fd1a800..216b810 100644 --- a/nihav-itu/src/codecs/h264/decoder_mt.rs +++ b/nihav-itu/src/codecs/h264/baseline/decoder_mt.rs @@ -1,6 +1,7 @@ use nihav_core::codecs::*; use nihav_core::io::bitreader::*; +use super::super::*; use super::*; use super::dispatch::*; diff --git a/nihav-itu/src/codecs/h264/decoder_st.rs b/nihav-itu/src/codecs/h264/baseline/decoder_st.rs similarity index 99% rename from nihav-itu/src/codecs/h264/decoder_st.rs rename to nihav-itu/src/codecs/h264/baseline/decoder_st.rs index 149cf74..8577117 100644 --- a/nihav-itu/src/codecs/h264/decoder_st.rs +++ b/nihav-itu/src/codecs/h264/baseline/decoder_st.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use nihav_core::codecs::*; use nihav_core::io::bitreader::*; +use super::super::*; use super::*; struct H264Decoder { diff --git a/nihav-itu/src/codecs/h264/dispatch.rs b/nihav-itu/src/codecs/h264/baseline/dispatch.rs similarity index 99% rename from nihav-itu/src/codecs/h264/dispatch.rs rename to nihav-itu/src/codecs/h264/baseline/dispatch.rs index 75afb26..e3e27fc 100644 --- a/nihav-itu/src/codecs/h264/dispatch.rs +++ b/nihav-itu/src/codecs/h264/baseline/dispatch.rs @@ -4,7 +4,8 @@ use std::thread; use nihav_core::codecs::{DecoderError, DecoderResult}; -use super::{FrameDecoder, PictureInfo, Shareable}; +use super::{FrameDecoder, PictureInfo}; +use super::super::Shareable; #[derive(Clone,Copy,Debug,PartialEq)] pub enum FrameDecodingStatus { diff --git a/nihav-itu/src/codecs/h264/dsp/mc/debug.rs b/nihav-itu/src/codecs/h264/baseline/dsp/mc/debug.rs similarity index 100% rename from nihav-itu/src/codecs/h264/dsp/mc/debug.rs rename to nihav-itu/src/codecs/h264/baseline/dsp/mc/debug.rs diff --git a/nihav-itu/src/codecs/h264/dsp/mc/mod.rs b/nihav-itu/src/codecs/h264/baseline/dsp/mc/mod.rs similarity index 100% rename from nihav-itu/src/codecs/h264/dsp/mc/mod.rs rename to nihav-itu/src/codecs/h264/baseline/dsp/mc/mod.rs diff --git a/nihav-itu/src/codecs/h264/dsp/mc/release.rs b/nihav-itu/src/codecs/h264/baseline/dsp/mc/release.rs similarity index 100% rename from nihav-itu/src/codecs/h264/dsp/mc/release.rs rename to nihav-itu/src/codecs/h264/baseline/dsp/mc/release.rs diff --git a/nihav-itu/src/codecs/h264/dsp/mc/x86/blockdsp.rs b/nihav-itu/src/codecs/h264/baseline/dsp/mc/x86/blockdsp.rs similarity index 100% rename from nihav-itu/src/codecs/h264/dsp/mc/x86/blockdsp.rs rename to nihav-itu/src/codecs/h264/baseline/dsp/mc/x86/blockdsp.rs diff --git a/nihav-itu/src/codecs/h264/dsp/mc/x86/chroma_mc.rs b/nihav-itu/src/codecs/h264/baseline/dsp/mc/x86/chroma_mc.rs similarity index 100% rename from nihav-itu/src/codecs/h264/dsp/mc/x86/chroma_mc.rs rename to nihav-itu/src/codecs/h264/baseline/dsp/mc/x86/chroma_mc.rs diff --git a/nihav-itu/src/codecs/h264/dsp/mc/x86/luma_mc.rs b/nihav-itu/src/codecs/h264/baseline/dsp/mc/x86/luma_mc.rs similarity index 100% rename from nihav-itu/src/codecs/h264/dsp/mc/x86/luma_mc.rs rename to nihav-itu/src/codecs/h264/baseline/dsp/mc/x86/luma_mc.rs diff --git a/nihav-itu/src/codecs/h264/dsp/mc/x86/mod.rs b/nihav-itu/src/codecs/h264/baseline/dsp/mc/x86/mod.rs similarity index 100% rename from nihav-itu/src/codecs/h264/dsp/mc/x86/mod.rs rename to nihav-itu/src/codecs/h264/baseline/dsp/mc/x86/mod.rs diff --git a/nihav-itu/src/codecs/h264/dsp/mod.rs b/nihav-itu/src/codecs/h264/baseline/dsp/mod.rs similarity index 100% rename from nihav-itu/src/codecs/h264/dsp/mod.rs rename to nihav-itu/src/codecs/h264/baseline/dsp/mod.rs diff --git a/nihav-itu/src/codecs/h264/loopfilter.rs b/nihav-itu/src/codecs/h264/baseline/loopfilter.rs similarity index 100% rename from nihav-itu/src/codecs/h264/loopfilter.rs rename to nihav-itu/src/codecs/h264/baseline/loopfilter.rs diff --git a/nihav-itu/src/codecs/h264/mb_recon.rs b/nihav-itu/src/codecs/h264/baseline/mb_recon.rs similarity index 99% rename from nihav-itu/src/codecs/h264/mb_recon.rs rename to nihav-itu/src/codecs/h264/baseline/mb_recon.rs index dc7302d..08fc30f 100644 --- a/nihav-itu/src/codecs/h264/mb_recon.rs +++ b/nihav-itu/src/codecs/h264/baseline/mb_recon.rs @@ -1,11 +1,12 @@ use nihav_core::codecs::{DecoderResult, DecoderError}; use nihav_core::frame::*; use nihav_codec_support::codecs::{MV, ZERO_MV}; -use super::{CurrentMBInfo, I4X4_SCAN, Shareable}; +use super::super::{CurrentMBInfo, I4X4_SCAN, Shareable}; +use super::super::common_types::*; use super::dispatch::{ThreadDispatcher, FrameDecodingStatus}; use super::dsp::*; use super::pic_ref::SimplifiedSliceRefs; -use super::slice::{SliceHeader, WeightInfo, DEF_WEIGHT_INFO}; +use super::super::slice::{SliceHeader, WeightInfo, DEF_WEIGHT_INFO}; use super::types::*; fn pred_intra(frm: &mut NASimpleVideoFrame, sstate: &SliceState, mb_info: &CurrentMBInfo) { diff --git a/nihav-itu/src/codecs/h264/baseline/mod.rs b/nihav-itu/src/codecs/h264/baseline/mod.rs new file mode 100644 index 0000000..89606fc --- /dev/null +++ b/nihav-itu/src/codecs/h264/baseline/mod.rs @@ -0,0 +1,30 @@ +mod types; +pub use types::*; +mod pic_ref; +pub use pic_ref::*; +#[allow(clippy::identity_op)] +#[allow(clippy::erasing_op)] +#[allow(clippy::many_single_char_names)] +#[allow(clippy::range_plus_one)] +mod dsp; +use dsp::*; +mod cabac; +use cabac::*; +use super::cabac_coder::*; +mod cavlc; +use cavlc::*; +mod loopfilter; +use loopfilter::*; +mod mb_recon; +use mb_recon::*; +use super::sets::*; +use super::slice::*; + +mod decoder_st; +pub use decoder_st::*; +mod dispatch; +mod decoder_mt; +pub use decoder_mt::*; + +use super::common_types::*; + diff --git a/nihav-itu/src/codecs/h264/pic_ref.rs b/nihav-itu/src/codecs/h264/baseline/pic_ref.rs similarity index 99% rename from nihav-itu/src/codecs/h264/pic_ref.rs rename to nihav-itu/src/codecs/h264/baseline/pic_ref.rs index b19f633..d01b746 100644 --- a/nihav-itu/src/codecs/h264/pic_ref.rs +++ b/nihav-itu/src/codecs/h264/baseline/pic_ref.rs @@ -2,8 +2,9 @@ use nihav_core::codecs::DecoderResult; use nihav_core::frame::{FrameType, NAVideoBufferRef, NATimeInfo}; use nihav_core::refs::*; use nihav_codec_support::codecs::MV; -use super::sets::SeqParameterSet; -use super::slice::*; +use super::super::common_types::*; +use super::super::sets::SeqParameterSet; +use super::super::slice::*; use super::types::*; #[derive(Clone)] diff --git a/nihav-itu/src/codecs/h264/types.rs b/nihav-itu/src/codecs/h264/baseline/types.rs similarity index 68% rename from nihav-itu/src/codecs/h264/types.rs rename to nihav-itu/src/codecs/h264/baseline/types.rs index 0cb3f8e..2f273a9 100644 --- a/nihav-itu/src/codecs/h264/types.rs +++ b/nihav-itu/src/codecs/h264/baseline/types.rs @@ -3,6 +3,7 @@ use nihav_codec_support::codecs::{MV, ZERO_MV}; use nihav_codec_support::data::GenericCache; use super::SimplifiedSliceRefs; use super::pic_ref::FrameMBInfo; +use super::super::common_types::*; #[derive(Clone,Copy)] pub struct SimpleFrame<'a> { @@ -26,391 +27,6 @@ impl<'a> SimpleFrame<'a> { } } -#[repr(u8)] -#[derive(Clone,Copy,Debug,PartialEq)] -pub enum BMode { - L0, - L1, - Bi, -} - -#[derive(Clone,Copy,Debug,PartialEq,Default)] -pub enum MBType { - #[default] - Intra4x4, - Intra8x8, - Intra16x16(u8, u8, u8), - PCM, - - P16x16, - P16x8, - P8x16, - P8x8, - P8x8Ref0, - PSkip, - - Direct, - B16x16(BMode), - B16x8(BMode, BMode), - B8x16(BMode, BMode), - B8x8, - BSkip, -} - -impl MBType { - pub fn is_intra(self) -> bool { - matches!(self, MBType::Intra4x4 | MBType::Intra8x8 | MBType::Intra16x16(_, _, _) | MBType::PCM) - } - pub fn is_intra16x16(self) -> bool { - matches!(self, MBType::Intra16x16(_, _, _)) - } - pub fn is_skip(self) -> bool { - matches!(self, MBType::PSkip | MBType::BSkip) - } - pub fn is_4x4(self) -> bool { self.num_parts() == 4 } - pub fn is_l0(self, part: usize) -> bool { - match self { - MBType::B16x16(mode) => mode == BMode::L0, - MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => { - if part == 0 { - mode0 == BMode::L0 - } else { - mode1 == BMode::L0 - } - }, - MBType::Direct | MBType::BSkip => false, - _ => true, - } - } - pub fn is_l1(self, part: usize) -> bool { - match self { - MBType::B16x16(mode) => mode == BMode::L1, - MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => { - if part == 0 { - mode0 == BMode::L1 - } else { - mode1 == BMode::L1 - } - }, - _ => false, - } - } - pub fn num_parts(self) -> usize { - match self { - MBType::Intra4x4 | MBType::Intra8x8 | MBType::Intra16x16(_, _, _) | MBType::PCM | - MBType::PSkip | - MBType::Direct | MBType::BSkip - => 1, - MBType::P16x16 | - MBType::B16x16(_) - => 1, - MBType::P16x8 | MBType::P8x16 | - MBType::B16x8(_, _) | MBType::B8x16(_, _) - => 2, - _ => 4, - } - } - pub fn size(self) -> (usize, usize) { - match self { - MBType::Intra4x4 | - MBType::Intra8x8 | - MBType::Intra16x16(_, _, _) | - MBType::PCM | - MBType::P16x16 | - MBType::PSkip | - MBType::Direct | - MBType::B16x16(_) | - MBType::BSkip - => (16, 16), - MBType::P16x8 | MBType::B16x8(_, _) => (16, 8), - MBType::P8x16 | MBType::B8x16(_, _) => (8, 16), - _ => (8, 8), - } - } -} - -#[derive(Clone,Copy,Debug,PartialEq,Default)] -pub enum SubMBType { - P8x8, - P8x4, - P4x8, - P4x4, - #[default] - Direct8x8, - B8x8(BMode), - B8x4(BMode), - B4x8(BMode), - B4x4(BMode), -} - -impl SubMBType { - pub fn num_parts(self) -> usize { - match self { - SubMBType::P8x8 | SubMBType::Direct8x8 | SubMBType::B8x8(_) => 1, - SubMBType::P4x4 | SubMBType::B4x4(_) => 4, - _ => 2, - } - } - pub fn size(self) -> (usize, usize) { - match self { - SubMBType::P8x8 | SubMBType::Direct8x8 | SubMBType::B8x8(_) => (8, 8), - SubMBType::P8x4 | SubMBType::B8x4(_) => (8, 4), - SubMBType::P4x8 | SubMBType::B4x8(_) => (4, 8), - SubMBType::P4x4 | SubMBType::B4x4(_) => (4, 4), - } - } - pub fn is_l0(self) -> bool { - match self { - SubMBType::B8x8(mode) | SubMBType::B8x4(mode) | - SubMBType::B4x8(mode) | SubMBType::B4x4(mode) => { - mode == BMode::L0 - }, - _ => true, - } - } - pub fn is_l1(self) -> bool { - match self { - SubMBType::B8x8(mode) | SubMBType::B8x4(mode) | - SubMBType::B4x8(mode) | SubMBType::B4x4(mode) => { - mode == BMode::L1 - }, - _ => false, - } - } -} - -#[repr(u8)] -#[derive(Clone,Copy,Debug,PartialEq,Default)] -pub enum CompactMBType { - Intra4x4, - Intra8x8, - Intra16x16, - PCM, - - P16x16, - P16x8, - P8x16, - P8x8, - P8x8Ref0, - PSkip, - - Direct, - B16x16, - B16x8, - B8x16, - B8x8, - BSkip, - - #[default] - None, -} - -impl CompactMBType { - pub fn is_intra(self) -> bool { - matches!(self, CompactMBType::Intra4x4 | CompactMBType::Intra8x8 | CompactMBType::Intra16x16) - } - pub fn is_intra16orpcm(self) -> bool { - matches!(self, CompactMBType::Intra16x16 | CompactMBType::PCM) - } - pub fn is_skip(self) -> bool { - matches!(self, CompactMBType::PSkip | CompactMBType::BSkip) - } - pub fn is_direct(self) -> bool { - matches!(self, CompactMBType::BSkip | CompactMBType::Direct | CompactMBType::None) - } - pub fn is_inter(self) -> bool { - !self.is_intra() && !self.is_skip() && self != CompactMBType::PCM - } - pub fn is_16x16_ref(self) -> bool { - matches!(self, - CompactMBType::Intra4x4 | - CompactMBType::Intra8x8 | - CompactMBType::Intra16x16 | - CompactMBType::PCM | - CompactMBType::P16x16 | - CompactMBType::B16x16) - } -} - -impl From for CompactMBType { - fn from(mbtype: MBType) -> Self { - match mbtype { - MBType::Intra4x4 => CompactMBType::Intra4x4, - MBType::Intra8x8 => CompactMBType::Intra8x8, - MBType::Intra16x16(_, _, _) => CompactMBType::Intra16x16, - MBType::PCM => CompactMBType::PCM, - MBType::P16x16 => CompactMBType::P16x16, - MBType::P16x8 => CompactMBType::P16x8, - MBType::P8x16 => CompactMBType::P8x16, - MBType::P8x8 => CompactMBType::P8x8, - MBType::P8x8Ref0 => CompactMBType::P8x8Ref0, - MBType::PSkip => CompactMBType::PSkip, - MBType::Direct => CompactMBType::Direct, - MBType::B16x16(_) => CompactMBType::B16x16, - MBType::B16x8(_, _) => CompactMBType::B16x8, - MBType::B8x16(_, _) => CompactMBType::B8x16, - MBType::B8x8 => CompactMBType::B8x8, - MBType::BSkip => CompactMBType::BSkip, - } - } -} - -#[repr(u8)] -#[derive(Clone,Copy,Debug,PartialEq,Default)] -pub enum IntraPredMode { - Vertical, - Horizontal, - DC, - DiagDownLeft, - DiagDownRight, - VerRight, - HorDown, - VerLeft, - HorUp, - #[default] - None, -} - -impl IntraPredMode { - pub fn is_none(self) -> bool { self == IntraPredMode::None } - pub fn into_pred_idx(self) -> i8 { - if !self.is_none() { - self as u8 as i8 - } else { - -1 - } - } -} - -impl From for IntraPredMode { - fn from(val: u8) -> Self { - match val { - 0 => IntraPredMode::Vertical, - 1 => IntraPredMode::Horizontal, - 2 => IntraPredMode::DC, - 3 => IntraPredMode::DiagDownLeft, - 4 => IntraPredMode::DiagDownRight, - 5 => IntraPredMode::VerRight, - 6 => IntraPredMode::HorDown, - 7 => IntraPredMode::VerLeft, - 8 => IntraPredMode::HorUp, - _ => IntraPredMode::None, - } - } -} - -impl From for u8 { - fn from(val: IntraPredMode) -> Self { - match val { - IntraPredMode::Vertical => 0, - IntraPredMode::Horizontal => 1, - IntraPredMode::DC => 2, - IntraPredMode::DiagDownLeft => 3, - IntraPredMode::DiagDownRight => 4, - IntraPredMode::VerRight => 5, - IntraPredMode::HorDown => 6, - IntraPredMode::VerLeft => 7, - IntraPredMode::HorUp => 8, - _ => 9, - } - } -} - -pub const MISSING_POC: u16 = 0xFFFF; - -#[derive(Clone,Copy,Debug)] -pub struct PicRef { - ref_idx: u8 -} - -pub const MISSING_REF: PicRef = PicRef { ref_idx: 0xFF }; -pub const INVALID_REF: PicRef = PicRef { ref_idx: 0xFE }; -pub const ZERO_REF: PicRef = PicRef { ref_idx: 0 }; -const DIRECT_FLAG: u8 = 0x40; - -impl PicRef { - pub fn new(ref_idx: u8) -> Self { - Self { ref_idx } - } - pub fn not_avail(self) -> bool { - self == MISSING_REF || self == INVALID_REF - } - pub fn index(self) -> usize { (self.ref_idx & !DIRECT_FLAG) as usize } - pub fn is_direct(self) -> bool { (self.ref_idx & DIRECT_FLAG) != 0 } - pub fn set_direct(&mut self) { self.ref_idx |= DIRECT_FLAG; } - fn min_pos(self, other: Self) -> Self { - match (self.not_avail(), other.not_avail()) { - (true, true) => self, - (false, true) => self, - (true, false) => other, - (false, false) => PicRef::new((self.ref_idx & !DIRECT_FLAG).min(other.ref_idx & !DIRECT_FLAG)), - } - } -} - -impl Default for PicRef { - fn default() -> Self { MISSING_REF } -} - -impl PartialEq for PicRef { - fn eq(&self, other: &Self) -> bool { - (self.ref_idx | DIRECT_FLAG) == (other.ref_idx | DIRECT_FLAG) - } -} - -impl std::fmt::Display for PicRef { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if *self == MISSING_REF { - write!(f, "-1") - } else if *self == INVALID_REF { - write!(f, "-2") - } else { - write!(f, "{}", self.ref_idx & !DIRECT_FLAG) - } - } -} - -#[derive(Clone,Copy,Default)] -pub struct MBData { - pub mb_type: CompactMBType, - pub cbp: u8, - pub coded_flags: u32, - pub cmode: u8, - pub qp_y: u8, - pub qp_u: u8, - pub qp_v: u8, - pub transform_8x8: bool, -} - -pub fn blk4_to_blk8(blk4: usize) -> usize { - /*const MAP: [usize; 16] = [ 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3 ]; - MAP[blk4 & 0xF]*/ - ((blk4 & 2) >> 1) | ((blk4 & 8) >> 2) -} - -#[derive(Clone,Copy)] -pub struct Blk8Data { - pub ref_idx: [PicRef; 2], - pub ncoded_c: [u8; 2], -} - -impl Default for Blk8Data { - fn default() -> Self { - Self { - ref_idx: [MISSING_REF; 2], - ncoded_c: [0; 2], - } - } -} - -#[derive(Clone,Copy,Default)] -pub struct Blk4Data { - pub ncoded: u8, - pub ipred: IntraPredMode, - pub mv: [MV; 2], - pub mvd: [MV; 2], -} - pub struct SliceState { pub mb_x: usize, pub mb_y: usize, @@ -435,12 +51,6 @@ pub struct SliceState { const BLK4_TO_D8: [usize; 16] = [ 0, 0, 3, 3, 0, 0, 3, 3, 12, 12, 15, 15, 12, 12, 15, 15 ]; -#[repr(align(8))] -#[derive(Default)] -struct MVCache { - data: [[MV; 2]; 25] -} - impl SliceState { pub fn new() -> Self { Self { @@ -954,28 +564,3 @@ impl SliceState { } } } - -#[cfg(not(target_arch="x86_64"))] -fn mvdiff4(mv1: &[MV; 2], mv2: &[MV; 2]) -> bool { - let mvd0 = mv1[0] - mv2[0]; - let mvd1 = mv1[1] - mv2[1]; - (mvd0.x.abs() >= 4) || (mvd0.y.abs() >= 4) || (mvd1.x.abs() >= 4) || (mvd1.y.abs() >= 4) -} - -#[cfg(target_arch="x86_64")] -fn mvdiff4(mv1: &[MV; 2], mv2: &[MV; 2]) -> bool { - unsafe { - let mut flag = false; - let ptr = std::mem::transmute::<*const MV, *const u64>(mv1.as_ptr()); - let mut m0 = *ptr; - let ptr = std::mem::transmute::<*const MV, *const u64>(mv2.as_ptr()); - let mut m1 = *ptr; - for _ in 0..4 { - let tmp = m0.wrapping_sub(m1) as u16; - flag |= tmp.wrapping_add(3) > 6; - m0 >>= 16; - m1 >>= 16; - } - flag - } -} diff --git a/nihav-itu/src/codecs/h264/common_types.rs b/nihav-itu/src/codecs/h264/common_types.rs new file mode 100644 index 0000000..ef21430 --- /dev/null +++ b/nihav-itu/src/codecs/h264/common_types.rs @@ -0,0 +1,417 @@ +use nihav_codec_support::codecs::MV; + +#[repr(u8)] +#[derive(Clone,Copy,Debug,PartialEq)] +pub enum BMode { + L0, + L1, + Bi, +} + +#[derive(Clone,Copy,Debug,PartialEq,Default)] +pub enum MBType { + #[default] + Intra4x4, + Intra8x8, + Intra16x16(u8, u8, u8), + PCM, + + P16x16, + P16x8, + P8x16, + P8x8, + P8x8Ref0, + PSkip, + + Direct, + B16x16(BMode), + B16x8(BMode, BMode), + B8x16(BMode, BMode), + B8x8, + BSkip, +} + +impl MBType { + pub fn is_intra(self) -> bool { + matches!(self, MBType::Intra4x4 | MBType::Intra8x8 | MBType::Intra16x16(_, _, _) | MBType::PCM) + } + pub fn is_intra16x16(self) -> bool { + matches!(self, MBType::Intra16x16(_, _, _)) + } + pub fn is_skip(self) -> bool { + matches!(self, MBType::PSkip | MBType::BSkip) + } + pub fn is_4x4(self) -> bool { self.num_parts() == 4 } + pub fn is_l0(self, part: usize) -> bool { + match self { + MBType::B16x16(mode) => mode == BMode::L0, + MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => { + if part == 0 { + mode0 == BMode::L0 + } else { + mode1 == BMode::L0 + } + }, + MBType::Direct | MBType::BSkip => false, + _ => true, + } + } + pub fn is_l1(self, part: usize) -> bool { + match self { + MBType::B16x16(mode) => mode == BMode::L1, + MBType::B16x8(mode0, mode1) | MBType::B8x16(mode0, mode1) => { + if part == 0 { + mode0 == BMode::L1 + } else { + mode1 == BMode::L1 + } + }, + _ => false, + } + } + pub fn num_parts(self) -> usize { + match self { + MBType::Intra4x4 | MBType::Intra8x8 | MBType::Intra16x16(_, _, _) | MBType::PCM | + MBType::PSkip | + MBType::Direct | MBType::BSkip + => 1, + MBType::P16x16 | + MBType::B16x16(_) + => 1, + MBType::P16x8 | MBType::P8x16 | + MBType::B16x8(_, _) | MBType::B8x16(_, _) + => 2, + _ => 4, + } + } + pub fn size(self) -> (usize, usize) { + match self { + MBType::Intra4x4 | + MBType::Intra8x8 | + MBType::Intra16x16(_, _, _) | + MBType::PCM | + MBType::P16x16 | + MBType::PSkip | + MBType::Direct | + MBType::B16x16(_) | + MBType::BSkip + => (16, 16), + MBType::P16x8 | MBType::B16x8(_, _) => (16, 8), + MBType::P8x16 | MBType::B8x16(_, _) => (8, 16), + _ => (8, 8), + } + } +} + +#[derive(Clone,Copy,Debug,PartialEq,Default)] +pub enum SubMBType { + P8x8, + P8x4, + P4x8, + P4x4, + #[default] + Direct8x8, + B8x8(BMode), + B8x4(BMode), + B4x8(BMode), + B4x4(BMode), +} + +impl SubMBType { + pub fn num_parts(self) -> usize { + match self { + SubMBType::P8x8 | SubMBType::Direct8x8 | SubMBType::B8x8(_) => 1, + SubMBType::P4x4 | SubMBType::B4x4(_) => 4, + _ => 2, + } + } + pub fn size(self) -> (usize, usize) { + match self { + SubMBType::P8x8 | SubMBType::Direct8x8 | SubMBType::B8x8(_) => (8, 8), + SubMBType::P8x4 | SubMBType::B8x4(_) => (8, 4), + SubMBType::P4x8 | SubMBType::B4x8(_) => (4, 8), + SubMBType::P4x4 | SubMBType::B4x4(_) => (4, 4), + } + } + pub fn is_l0(self) -> bool { + match self { + SubMBType::B8x8(mode) | SubMBType::B8x4(mode) | + SubMBType::B4x8(mode) | SubMBType::B4x4(mode) => { + mode == BMode::L0 + }, + _ => true, + } + } + pub fn is_l1(self) -> bool { + match self { + SubMBType::B8x8(mode) | SubMBType::B8x4(mode) | + SubMBType::B4x8(mode) | SubMBType::B4x4(mode) => { + mode == BMode::L1 + }, + _ => false, + } + } +} + +#[repr(u8)] +#[derive(Clone,Copy,Debug,PartialEq,Default)] +pub enum CompactMBType { + Intra4x4, + Intra8x8, + Intra16x16, + PCM, + + P16x16, + P16x8, + P8x16, + P8x8, + P8x8Ref0, + PSkip, + + Direct, + B16x16, + B16x8, + B8x16, + B8x8, + BSkip, + + #[default] + None, +} + +impl CompactMBType { + pub fn is_intra(self) -> bool { + matches!(self, CompactMBType::Intra4x4 | CompactMBType::Intra8x8 | CompactMBType::Intra16x16) + } + pub fn is_intra16orpcm(self) -> bool { + matches!(self, CompactMBType::Intra16x16 | CompactMBType::PCM) + } + pub fn is_skip(self) -> bool { + matches!(self, CompactMBType::PSkip | CompactMBType::BSkip) + } + pub fn is_direct(self) -> bool { + matches!(self, CompactMBType::BSkip | CompactMBType::Direct | CompactMBType::None) + } + pub fn is_inter(self) -> bool { + !self.is_intra() && !self.is_skip() && self != CompactMBType::PCM + } + pub fn is_16x16_ref(self) -> bool { + matches!(self, + CompactMBType::Intra4x4 | + CompactMBType::Intra8x8 | + CompactMBType::Intra16x16 | + CompactMBType::PCM | + CompactMBType::P16x16 | + CompactMBType::B16x16) + } +} + +impl From for CompactMBType { + fn from(mbtype: MBType) -> Self { + match mbtype { + MBType::Intra4x4 => CompactMBType::Intra4x4, + MBType::Intra8x8 => CompactMBType::Intra8x8, + MBType::Intra16x16(_, _, _) => CompactMBType::Intra16x16, + MBType::PCM => CompactMBType::PCM, + MBType::P16x16 => CompactMBType::P16x16, + MBType::P16x8 => CompactMBType::P16x8, + MBType::P8x16 => CompactMBType::P8x16, + MBType::P8x8 => CompactMBType::P8x8, + MBType::P8x8Ref0 => CompactMBType::P8x8Ref0, + MBType::PSkip => CompactMBType::PSkip, + MBType::Direct => CompactMBType::Direct, + MBType::B16x16(_) => CompactMBType::B16x16, + MBType::B16x8(_, _) => CompactMBType::B16x8, + MBType::B8x16(_, _) => CompactMBType::B8x16, + MBType::B8x8 => CompactMBType::B8x8, + MBType::BSkip => CompactMBType::BSkip, + } + } +} + +#[repr(u8)] +#[derive(Clone,Copy,Debug,PartialEq,Default)] +pub enum IntraPredMode { + Vertical, + Horizontal, + DC, + DiagDownLeft, + DiagDownRight, + VerRight, + HorDown, + VerLeft, + HorUp, + #[default] + None, +} + +impl IntraPredMode { + pub fn is_none(self) -> bool { self == IntraPredMode::None } + pub fn into_pred_idx(self) -> i8 { + if !self.is_none() { + self as u8 as i8 + } else { + -1 + } + } +} + +impl From for IntraPredMode { + fn from(val: u8) -> Self { + match val { + 0 => IntraPredMode::Vertical, + 1 => IntraPredMode::Horizontal, + 2 => IntraPredMode::DC, + 3 => IntraPredMode::DiagDownLeft, + 4 => IntraPredMode::DiagDownRight, + 5 => IntraPredMode::VerRight, + 6 => IntraPredMode::HorDown, + 7 => IntraPredMode::VerLeft, + 8 => IntraPredMode::HorUp, + _ => IntraPredMode::None, + } + } +} + +impl From for u8 { + fn from(val: IntraPredMode) -> Self { + match val { + IntraPredMode::Vertical => 0, + IntraPredMode::Horizontal => 1, + IntraPredMode::DC => 2, + IntraPredMode::DiagDownLeft => 3, + IntraPredMode::DiagDownRight => 4, + IntraPredMode::VerRight => 5, + IntraPredMode::HorDown => 6, + IntraPredMode::VerLeft => 7, + IntraPredMode::HorUp => 8, + _ => 9, + } + } +} + +pub const MISSING_POC: u16 = 0xFFFF; + +#[derive(Clone,Copy,Debug)] +pub struct PicRef { + ref_idx: u8 +} + +pub const MISSING_REF: PicRef = PicRef { ref_idx: 0xFF }; +pub const INVALID_REF: PicRef = PicRef { ref_idx: 0xFE }; +pub const ZERO_REF: PicRef = PicRef { ref_idx: 0 }; +const DIRECT_FLAG: u8 = 0x40; + +impl PicRef { + pub fn new(ref_idx: u8) -> Self { + Self { ref_idx } + } + pub fn not_avail(self) -> bool { + self == MISSING_REF || self == INVALID_REF + } + pub fn index(self) -> usize { (self.ref_idx & !DIRECT_FLAG) as usize } + pub fn is_direct(self) -> bool { (self.ref_idx & DIRECT_FLAG) != 0 } + pub fn set_direct(&mut self) { self.ref_idx |= DIRECT_FLAG; } + pub fn min_pos(self, other: Self) -> Self { + match (self.not_avail(), other.not_avail()) { + (true, true) => self, + (false, true) => self, + (true, false) => other, + (false, false) => PicRef::new((self.ref_idx & !DIRECT_FLAG).min(other.ref_idx & !DIRECT_FLAG)), + } + } +} + +impl Default for PicRef { + fn default() -> Self { MISSING_REF } +} + +impl PartialEq for PicRef { + fn eq(&self, other: &Self) -> bool { + (self.ref_idx | DIRECT_FLAG) == (other.ref_idx | DIRECT_FLAG) + } +} + +impl std::fmt::Display for PicRef { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if *self == MISSING_REF { + write!(f, "-1") + } else if *self == INVALID_REF { + write!(f, "-2") + } else { + write!(f, "{}", self.ref_idx & !DIRECT_FLAG) + } + } +} + +#[derive(Clone,Copy,Default)] +pub struct MBData { + pub mb_type: CompactMBType, + pub cbp: u8, + pub coded_flags: u32, + pub cmode: u8, + pub qp_y: u8, + pub qp_u: u8, + pub qp_v: u8, + pub transform_8x8: bool, +} + +pub fn blk4_to_blk8(blk4: usize) -> usize { + /*const MAP: [usize; 16] = [ 0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3 ]; + MAP[blk4 & 0xF]*/ + ((blk4 & 2) >> 1) | ((blk4 & 8) >> 2) +} + +#[derive(Clone,Copy)] +pub struct Blk8Data { + pub ref_idx: [PicRef; 2], + pub ncoded_c: [u8; 2], +} + +impl Default for Blk8Data { + fn default() -> Self { + Self { + ref_idx: [MISSING_REF; 2], + ncoded_c: [0; 2], + } + } +} + +#[derive(Clone,Copy,Default)] +pub struct Blk4Data { + pub ncoded: u8, + pub ipred: IntraPredMode, + pub mv: [MV; 2], + pub mvd: [MV; 2], +} + +#[repr(align(8))] +#[derive(Default)] +pub struct MVCache { + pub data: [[MV; 2]; 25] +} + +#[cfg(not(target_arch="x86_64"))] +pub fn mvdiff4(mv1: &[MV; 2], mv2: &[MV; 2]) -> bool { + let mvd0 = mv1[0] - mv2[0]; + let mvd1 = mv1[1] - mv2[1]; + (mvd0.x.abs() >= 4) || (mvd0.y.abs() >= 4) || (mvd1.x.abs() >= 4) || (mvd1.y.abs() >= 4) +} + +#[cfg(target_arch="x86_64")] +pub fn mvdiff4(mv1: &[MV; 2], mv2: &[MV; 2]) -> bool { + unsafe { + let mut flag = false; + let ptr = std::mem::transmute::<*const MV, *const u64>(mv1.as_ptr()); + let mut m0 = *ptr; + let ptr = std::mem::transmute::<*const MV, *const u64>(mv2.as_ptr()); + let mut m1 = *ptr; + for _ in 0..4 { + let tmp = m0.wrapping_sub(m1) as u16; + flag |= tmp.wrapping_add(3) > 6; + m0 >>= 16; + m1 >>= 16; + } + flag + } +} diff --git a/nihav-itu/src/codecs/h264/mod.rs b/nihav-itu/src/codecs/h264/mod.rs index e334997..52e8d0e 100644 --- a/nihav-itu/src/codecs/h264/mod.rs +++ b/nihav-itu/src/codecs/h264/mod.rs @@ -12,38 +12,16 @@ use nihav_core::io::bitreader::*; use nihav_core::io::intcode::*; use nihav_codec_support::codecs::{MV, ZERO_MV}; -pub type Shareable = Arc>; - -mod types; -pub use types::*; -mod pic_ref; -pub use pic_ref::*; -#[allow(clippy::identity_op)] -#[allow(clippy::erasing_op)] -#[allow(clippy::many_single_char_names)] -#[allow(clippy::range_plus_one)] -mod dsp; -use dsp::*; -mod cabac; -use cabac::*; +mod baseline; mod cabac_coder; -use cabac_coder::*; -mod cavlc; -use cavlc::*; -mod loopfilter; -use loopfilter::*; -mod mb_recon; -use mb_recon::*; +mod common_types; +use common_types::*; +pub use baseline::{get_decoder, get_decoder_mt}; mod sets; -use sets::*; mod slice; use slice::*; -mod decoder_st; -pub use decoder_st::*; -mod dispatch; -mod decoder_mt; -pub use decoder_mt::*; +pub type Shareable = Arc>; trait ReadUE { fn read_ue(&mut self) -> DecoderResult; @@ -82,25 +60,6 @@ impl<'a> ReadUE for BitReader<'a> { } } -#[derive(Clone,Copy)] -pub struct Coeff8x8 { - pub coeffs: [i16; 64], -} - -impl Coeff8x8 { - fn clear(&mut self) { - self.coeffs = [0; 64]; - } -} - -impl Default for Coeff8x8 { - fn default() -> Self { - Self { - coeffs: [0; 64], - } - } -} - #[derive(Clone,Copy,Default)] pub struct CurrentMBInfo { pub mb_type: MBType, @@ -149,6 +108,25 @@ impl CurrentMBInfo { } } +#[derive(Clone,Copy)] +pub struct Coeff8x8 { + pub coeffs: [i16; 64], +} + +impl Coeff8x8 { + fn clear(&mut self) { + self.coeffs = [0; 64]; + } +} + +impl Default for Coeff8x8 { + fn default() -> Self { + Self { + coeffs: [0; 64], + } + } +} + fn get_long_term_id(is_idr: bool, slice_hdr: &SliceHeader) -> Option { if is_idr && !slice_hdr.long_term_reference { None -- 2.39.5