mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-09-03 18:23:49 +00:00
Update to bitstream-io 3
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/2211>
This commit is contained in:
parent
6f7a1e21d5
commit
1ea767ac2a
24 changed files with 158 additions and 278 deletions
30
Cargo.lock
generated
30
Cargo.lock
generated
|
@ -1015,6 +1015,15 @@ version = "2.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2"
|
||||
|
||||
[[package]]
|
||||
name = "bitstream-io"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "680575de65ce8b916b82a447458b94a48776707d9c2681a9d8da351c06886a1f"
|
||||
dependencies = [
|
||||
"core2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
|
@ -1428,6 +1437,15 @@ version = "0.8.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "core2"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
|
@ -2668,7 +2686,7 @@ version = "0.14.0-alpha.1"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"atomic_refcell",
|
||||
"bitstream-io",
|
||||
"bitstream-io 3.2.0",
|
||||
"byteorder",
|
||||
"cairo-rs",
|
||||
"cdp-types",
|
||||
|
@ -2779,7 +2797,7 @@ name = "gst-plugin-fmp4"
|
|||
version = "0.14.0-alpha.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitstream-io",
|
||||
"bitstream-io 3.2.0",
|
||||
"chrono",
|
||||
"dash-mpd",
|
||||
"gst-plugin-version-helper",
|
||||
|
@ -2959,7 +2977,7 @@ name = "gst-plugin-mp4"
|
|||
version = "0.14.0-alpha.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitstream-io",
|
||||
"bitstream-io 3.2.0",
|
||||
"gst-plugin-version-helper",
|
||||
"gstreamer",
|
||||
"gstreamer-audio",
|
||||
|
@ -2977,7 +2995,7 @@ name = "gst-plugin-mpegtslive"
|
|||
version = "0.14.0-alpha.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitstream-io",
|
||||
"bitstream-io 3.2.0",
|
||||
"gst-plugin-version-helper",
|
||||
"gstreamer",
|
||||
"smallvec",
|
||||
|
@ -3148,7 +3166,7 @@ version = "0.14.0-alpha.1"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"atomic_refcell",
|
||||
"bitstream-io",
|
||||
"bitstream-io 3.2.0",
|
||||
"byte-slice-cast",
|
||||
"chrono",
|
||||
"futures",
|
||||
|
@ -6402,7 +6420,7 @@ dependencies = [
|
|||
"arg_enum_proc_macro",
|
||||
"arrayvec",
|
||||
"av1-grain",
|
||||
"bitstream-io",
|
||||
"bitstream-io 2.6.0",
|
||||
"built",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
|
|
|
@ -16,7 +16,7 @@ gst-audio = { workspace = true, features = ["v1_18"] }
|
|||
gst-video = { workspace = true, features = ["v1_18"] }
|
||||
gst-pbutils = { workspace = true, features = ["v1_20"] }
|
||||
gst-tag = { workspace = true, features = ["v1_20"] }
|
||||
bitstream-io = "2.3"
|
||||
bitstream-io = "3"
|
||||
|
||||
[lib]
|
||||
name = "gstfmp4"
|
||||
|
|
|
@ -20,7 +20,7 @@ where
|
|||
let mut num_bytes = 0;
|
||||
|
||||
for i in 0..8 {
|
||||
let byte = reader.read::<u32>(8)?;
|
||||
let byte = reader.read::<8, u32>()?;
|
||||
value |= (byte & 0x7f) << (i * 7);
|
||||
num_bytes += 1;
|
||||
if byte & 0x80 == 0 {
|
||||
|
@ -91,7 +91,7 @@ impl SizedObu {
|
|||
));
|
||||
}
|
||||
|
||||
let obu_type = reader.read::<u8>(4)?.into();
|
||||
let obu_type = reader.read::<4, u8>()?.into();
|
||||
let has_extension = reader.read_bit()?;
|
||||
|
||||
// require a size field
|
||||
|
@ -106,7 +106,7 @@ impl SizedObu {
|
|||
let _ = reader.read_bit()?;
|
||||
|
||||
let (temporal_id, spatial_id) = if has_extension {
|
||||
(reader.read::<u8>(3)?, reader.read::<u8>(2)?)
|
||||
(reader.read::<3, u8>()?, reader.read::<2, u8>()?)
|
||||
} else {
|
||||
(0, 0)
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ gst-audio = { workspace = true, features = ["v1_18"] }
|
|||
gst-video = { workspace = true, features = ["v1_20"] }
|
||||
gst-pbutils = { workspace = true, features = ["v1_18"] }
|
||||
gst-tag = { workspace = true, features = ["v1_18"] }
|
||||
bitstream-io = "2.3"
|
||||
bitstream-io = "3"
|
||||
num-integer = { version = "0.1", default-features = false, features = [] }
|
||||
|
||||
[lib]
|
||||
|
|
|
@ -20,7 +20,7 @@ where
|
|||
let mut num_bytes = 0;
|
||||
|
||||
for i in 0..8 {
|
||||
let byte = reader.read::<u32>(8)?;
|
||||
let byte = reader.read::<8, u32>()?;
|
||||
value |= (byte & 0x7f) << (i * 7);
|
||||
num_bytes += 1;
|
||||
if byte & 0x80 == 0 {
|
||||
|
@ -91,7 +91,7 @@ impl SizedObu {
|
|||
));
|
||||
}
|
||||
|
||||
let obu_type = reader.read::<u8>(4)?.into();
|
||||
let obu_type = reader.read::<4, u8>()?.into();
|
||||
let has_extension = reader.read_bit()?;
|
||||
|
||||
// require a size field
|
||||
|
@ -106,7 +106,7 @@ impl SizedObu {
|
|||
let _ = reader.read_bit()?;
|
||||
|
||||
let (temporal_id, spatial_id) = if has_extension {
|
||||
(reader.read::<u8>(3)?, reader.read::<u8>(2)?)
|
||||
(reader.read::<3, u8>()?, reader.read::<2, u8>()?)
|
||||
} else {
|
||||
(0, 0)
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ rust-version.workspace = true
|
|||
|
||||
[dependencies]
|
||||
gst.workspace = true
|
||||
bitstream-io = "2.3"
|
||||
bitstream-io = "3"
|
||||
anyhow = "1"
|
||||
smallvec = "1"
|
||||
|
||||
|
|
|
@ -252,7 +252,7 @@ impl FromBitStream for TableHeader {
|
|||
let table_id = r.read_to::<u8>().context("table_id")?;
|
||||
let section_syntax_indicator = r.read_bit().context("table_syntax_indicator")?;
|
||||
r.skip(5).context("reserved")?;
|
||||
let section_length = r.read::<u16>(10).context("section_length")?;
|
||||
let section_length = r.read::<10, u16>().context("section_length")?;
|
||||
|
||||
Ok(TableHeader {
|
||||
table_id,
|
||||
|
@ -280,7 +280,7 @@ impl FromBitStream for TableSyntaxSection {
|
|||
{
|
||||
let table_id_extension = r.read_to::<u16>().context("table_id_extension")?;
|
||||
r.skip(2).context("reserved")?;
|
||||
let version_number = r.read::<u8>(5).context("version_number")?;
|
||||
let version_number = r.read::<5, u8>().context("version_number")?;
|
||||
let current_next_indicator = r.read_bit().context("current_next_indicator")?;
|
||||
let section_number = r.read_to::<u8>().context("section_number")?;
|
||||
let last_section_number = r.read_to::<u8>().context("last_section_number")?;
|
||||
|
@ -310,7 +310,7 @@ impl FromBitStream for ProgramAccessTable {
|
|||
{
|
||||
let program_num = r.read_to::<u16>().context("program_num")?;
|
||||
r.skip(3).context("reserved")?;
|
||||
let program_map_pid = r.read::<u16>(13).context("program_map_pid")?;
|
||||
let program_map_pid = r.read::<13, u16>().context("program_map_pid")?;
|
||||
|
||||
Ok(ProgramAccessTable {
|
||||
program_num,
|
||||
|
@ -334,11 +334,11 @@ impl FromBitStream for ProgramMappingTable {
|
|||
Self: Sized,
|
||||
{
|
||||
r.skip(3).context("reserved")?;
|
||||
let pcr_pid = r.read::<u16>(13).context("pcr_pid")?;
|
||||
let pcr_pid = r.read::<13, u16>().context("pcr_pid")?;
|
||||
r.skip(4).context("reserved")?;
|
||||
r.skip(2).context("program_info_length_unused")?;
|
||||
|
||||
let program_info_length = r.read::<u16>(10).context("program_info_length")?;
|
||||
let program_info_length = r.read::<10, u16>().context("program_info_length")?;
|
||||
r.skip(8 * program_info_length as u32)
|
||||
.context("program_descriptors")?;
|
||||
|
||||
|
@ -364,7 +364,7 @@ impl FromBitStream for ProgramMappingTable {
|
|||
};
|
||||
|
||||
let Some(elementary_pid) =
|
||||
try_read(r, |r| r.read::<u16>(13)).context("elementary_pid")?
|
||||
try_read(r, |r| r.read::<13, u16>()).context("elementary_pid")?
|
||||
else {
|
||||
break;
|
||||
};
|
||||
|
@ -378,7 +378,7 @@ impl FromBitStream for ProgramMappingTable {
|
|||
};
|
||||
|
||||
let Some(es_info_length) =
|
||||
try_read(r, |r| r.read::<u16>(10)).context("es_info_length")?
|
||||
try_read(r, |r| r.read::<10, u16>()).context("es_info_length")?
|
||||
else {
|
||||
break;
|
||||
};
|
||||
|
@ -632,11 +632,11 @@ impl FromBitStream for PacketHeader {
|
|||
let tei = r.read_bit().context("tei")?;
|
||||
let pusi = r.read_bit().context("pusi")?;
|
||||
let tp = r.read_bit().context("tp")?;
|
||||
let pid = r.read::<u16>(13).context("pid")?;
|
||||
let pid = r.read::<13, u16>().context("pid")?;
|
||||
|
||||
let tsc = r.read::<u8>(2).context("tsc")?;
|
||||
let afc = r.read::<u8>(2).context("afc")?;
|
||||
let cc = r.read::<u8>(4).context("cc")?;
|
||||
let tsc = r.read::<2, u8>().context("tsc")?;
|
||||
let afc = r.read::<2, u8>().context("afc")?;
|
||||
let cc = r.read::<4, u8>().context("cc")?;
|
||||
|
||||
Ok(PacketHeader {
|
||||
tei,
|
||||
|
@ -671,9 +671,9 @@ impl FromBitStream for AdaptionField {
|
|||
|
||||
// PCR present
|
||||
let pcr = if pcr_present {
|
||||
let pcr = r.read::<u64>(33).context("pcr_base")? * 300;
|
||||
let pcr = r.read::<33, u64>().context("pcr_base")? * 300;
|
||||
r.skip(6).context("pcr_reserved")?;
|
||||
let pcr = pcr + r.read::<u64>(9).context("pcr_extension")? % 300;
|
||||
let pcr = pcr + r.read::<9, u64>().context("pcr_extension")? % 300;
|
||||
Some(pcr)
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -11,7 +11,7 @@ rust-version.workspace = true
|
|||
[dependencies]
|
||||
anyhow = "1"
|
||||
atomic_refcell = "0.1"
|
||||
bitstream-io = "2.4"
|
||||
bitstream-io = "3"
|
||||
byte-slice-cast = "1.2"
|
||||
chrono = { version = "0.4", default-features = false }
|
||||
gst = { workspace = true, features = ["v1_20"] }
|
||||
|
|
|
@ -279,7 +279,7 @@ impl RtpBaseDepay2Impl for RtpAmrDepay {
|
|||
}
|
||||
|
||||
if frame_size > 0 {
|
||||
match r.read::<u8>(frame_size) {
|
||||
match r.read_var::<u8>(frame_size) {
|
||||
Ok(b) => {
|
||||
out_data.push(b << (8 - frame_size));
|
||||
}
|
||||
|
|
|
@ -681,7 +681,7 @@ impl RtpAmrPay {
|
|||
}
|
||||
|
||||
if num_bits > 0 {
|
||||
if let Err(err) = w.write(num_bits as u32, data[0] >> (8 - num_bits)) {
|
||||
if let Err(err) = w.write_var(num_bits as u32, data[0] >> (8 - num_bits)) {
|
||||
gst::error!(CAT, imp = self, "Failed writing payload: {err}");
|
||||
return Err(gst::FlowError::Error);
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ impl FromBitStreamWith<'_> for PayloadHeader {
|
|||
bail!("CRC not allowed in bandwidth-efficient mode");
|
||||
}
|
||||
|
||||
let cmr = r.read::<u8>(4).context("cmr")?;
|
||||
let cmr = r.read::<4, u8>().context("cmr")?;
|
||||
|
||||
let mut toc_entries = SmallVec::<[TocEntry; 16]>::new();
|
||||
loop {
|
||||
|
@ -184,7 +184,7 @@ impl ToBitStreamWith<'_> for PayloadHeader {
|
|||
bail!("No TOC entries");
|
||||
}
|
||||
|
||||
w.write::<u8>(4, self.cmr).context("cmr")?;
|
||||
w.write::<4, u8>(self.cmr).context("cmr")?;
|
||||
|
||||
for (i, entry) in self.toc_entries.iter().enumerate() {
|
||||
let mut entry = entry.clone();
|
||||
|
@ -256,7 +256,7 @@ impl FromBitStreamWith<'_> for TocEntry {
|
|||
Self: Sized,
|
||||
{
|
||||
let last = !r.read_bit().context("last")?;
|
||||
let frame_type = r.read::<u8>(4).context("frame_type")?;
|
||||
let frame_type = r.read::<4, u8>().context("frame_type")?;
|
||||
let frame_quality_indicator = r.read_bit().context("q")?;
|
||||
|
||||
if !cfg.wide_band && (9..=14).contains(&frame_type) {
|
||||
|
@ -331,7 +331,7 @@ impl ToBitStreamWith<'_> for TocEntry {
|
|||
}
|
||||
|
||||
w.write_bit(!self.last).context("last")?;
|
||||
w.write::<u8>(4, self.frame_type).context("frame_type")?;
|
||||
w.write::<4, u8>(self.frame_type).context("frame_type")?;
|
||||
w.write_bit(self.frame_quality_indicator)
|
||||
.context("frame_quality_indicator")?;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ where
|
|||
let mut num_bytes = 0;
|
||||
|
||||
for i in 0..8 {
|
||||
let byte = reader.read::<u32>(8)?;
|
||||
let byte = reader.read::<8, u32>()?;
|
||||
value |= (byte & 0x7f) << (i * 7);
|
||||
num_bytes += 1;
|
||||
if byte & 0x80 == 0 {
|
||||
|
@ -40,7 +40,7 @@ where
|
|||
{
|
||||
loop {
|
||||
writer.write_bit(value > 0x7f)?;
|
||||
writer.write(7, value & 0x7f)?;
|
||||
writer.write::<7, u32>(value & 0x7f)?;
|
||||
value >>= 7;
|
||||
if value == 0 {
|
||||
writer.byte_align()?;
|
||||
|
|
|
@ -80,7 +80,7 @@ impl UnsizedObu {
|
|||
));
|
||||
}
|
||||
|
||||
let obu_type = reader.read::<u8>(4)?.into();
|
||||
let obu_type = reader.read::<4, u8>()?.into();
|
||||
let has_extension = reader.read_bit()?;
|
||||
|
||||
let has_size_field = reader.read_bit()?;
|
||||
|
@ -89,7 +89,7 @@ impl UnsizedObu {
|
|||
let _ = reader.read_bit()?;
|
||||
|
||||
let (temporal_id, spatial_id) = if has_extension {
|
||||
(reader.read::<u8>(3)?, reader.read::<u8>(2)?)
|
||||
(reader.read::<3, u8>()?, reader.read::<2, u8>()?)
|
||||
} else {
|
||||
(0, 0)
|
||||
};
|
||||
|
@ -146,7 +146,7 @@ impl SizedObu {
|
|||
));
|
||||
}
|
||||
|
||||
let obu_type = reader.read::<u8>(4)?.into();
|
||||
let obu_type = reader.read::<4, u8>()?.into();
|
||||
let has_extension = reader.read_bit()?;
|
||||
|
||||
// require a size field
|
||||
|
@ -161,7 +161,7 @@ impl SizedObu {
|
|||
let _ = reader.read_bit()?;
|
||||
|
||||
let (temporal_id, spatial_id) = if has_extension {
|
||||
(reader.read::<u8>(3)?, reader.read::<u8>(2)?)
|
||||
(reader.read::<3, u8>()?, reader.read::<2, u8>()?)
|
||||
} else {
|
||||
(0, 0)
|
||||
};
|
||||
|
|
|
@ -77,15 +77,15 @@ impl FromBitStream for StreamMuxConfig {
|
|||
// numProgram == 0 means 1 program (4 bits)
|
||||
// numLayer == 0 means 1 layer (3 bits)
|
||||
|
||||
if r.read::<u8>(1).context("audioMuxVersion")? != 0 {
|
||||
if r.read::<1, u8>().context("audioMuxVersion")? != 0 {
|
||||
Err(UnknownVersion)?;
|
||||
}
|
||||
|
||||
let _ = r.read_bit().context("allStreamsSameTimeFraming")?;
|
||||
let num_sub_frames = r.read::<u8>(6).context("numSubFrames")? + 1;
|
||||
let num_sub_frames = r.read::<6, u8>().context("numSubFrames")? + 1;
|
||||
|
||||
let num_progs = r.read::<u8>(4).context("numProgram")? + 1;
|
||||
let num_layers = r.read::<u8>(3).context("numLayer")? + 1;
|
||||
let num_progs = r.read::<4, u8>().context("numProgram")? + 1;
|
||||
let num_layers = r.read::<3, u8>().context("numLayer")? + 1;
|
||||
if !(num_progs == 1 && num_layers == 1) {
|
||||
// Same as for rtpmp4adepay
|
||||
Err(UnsupportedProgsLayer {
|
||||
|
@ -127,24 +127,24 @@ impl FromBitStream for AudioSpecificConfig {
|
|||
fn from_reader<R: BitRead + ?Sized>(r: &mut R) -> anyhow::Result<Self> {
|
||||
use MPEG4AudioParserError::*;
|
||||
|
||||
let audio_object_type = r.read(5).context("audioObjectType")?;
|
||||
let audio_object_type = r.read::<5, _>().context("audioObjectType")?;
|
||||
if audio_object_type == 0 {
|
||||
Err(InvalidAudioObjectType0)?;
|
||||
}
|
||||
|
||||
let sampling_freq_idx = r.read::<u8>(4).context("samplingFrequencyIndex")?;
|
||||
let sampling_freq_idx = r.read::<4, u8>().context("samplingFrequencyIndex")?;
|
||||
if sampling_freq_idx as usize >= ACC_SAMPLING_FREQS.len() && sampling_freq_idx != 0xf {
|
||||
Err(InvalidSamplingFreqIdx(sampling_freq_idx))?;
|
||||
}
|
||||
|
||||
// RTP rate depends on sampling freq of the audio
|
||||
let sampling_freq = if sampling_freq_idx == 0xf {
|
||||
r.read(24).context("samplingFrequency")?
|
||||
r.read::<24, _>().context("samplingFrequency")?
|
||||
} else {
|
||||
ACC_SAMPLING_FREQS[sampling_freq_idx as usize]
|
||||
};
|
||||
|
||||
let channel_conf = r.read(4).context("channelConfiguration")?;
|
||||
let channel_conf = r.read::<4, _>().context("channelConfiguration")?;
|
||||
if channel_conf > 7 {
|
||||
Err(InvalidChannels(channel_conf))?;
|
||||
}
|
||||
|
|
|
@ -146,18 +146,18 @@ impl ConfigWithCodecData {
|
|||
// numProgram == 0 means 1 program (4 bits)
|
||||
// numLayer == 0 means 1 layer (3 bits)
|
||||
|
||||
w.write(1, 0).unwrap();
|
||||
w.write::<1, _>(0).unwrap();
|
||||
w.write_bit(true).unwrap();
|
||||
w.write(13, 0).unwrap();
|
||||
w.write::<13, _>(0).unwrap();
|
||||
// 1 bit missing for byte alignment
|
||||
|
||||
// Append AudioSpecificConfig for prog 1 layer 1 (from codec_data)
|
||||
for byte in codec_data_ref.as_slice() {
|
||||
w.write(8, *byte).context("appending codec_data")?
|
||||
w.write::<8, _>(*byte).context("appending codec_data")?
|
||||
}
|
||||
|
||||
// Padding
|
||||
w.write(7, 0).unwrap();
|
||||
w.write::<7, _>(0).unwrap();
|
||||
|
||||
Ok(ConfigWithCodecData {
|
||||
audio_config,
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
use bitstream_io::{BitRead, BitWrite, FromBitStreamWith, ToBitStreamWith};
|
||||
|
||||
use crate::mp4g::{AccessUnitIndex, ModeConfig};
|
||||
use crate::utils::{mask_valid_2_comp, raw_2_comp_to_i32};
|
||||
|
||||
#[derive(thiserror::Error, Debug, PartialEq, Eq)]
|
||||
pub enum AuHeaderError {
|
||||
|
@ -21,18 +20,6 @@ pub enum AuHeaderError {
|
|||
|
||||
#[error("Unexpected CTS flag set for the first AU header {}", .0)]
|
||||
CtsFlagSetInFirstAuHeader(AccessUnitIndex),
|
||||
|
||||
#[error("Out of range CTS-delta {cts_delta} for AU {index}")]
|
||||
OutOfRangeSizeCtsDelta {
|
||||
cts_delta: i32,
|
||||
index: AccessUnitIndex,
|
||||
},
|
||||
|
||||
#[error("Out of range DTS-delta {dts_delta} for AU {index}")]
|
||||
OutOfRangeSizeDtsDelta {
|
||||
dts_delta: i32,
|
||||
index: AccessUnitIndex,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -76,7 +63,7 @@ impl<'a> FromBitStreamWith<'a> for AuHeader {
|
|||
|
||||
if ctx.config.size_len > 0 {
|
||||
let val = r
|
||||
.read::<u32>(ctx.config.size_len as u32)
|
||||
.read_var::<u32>(ctx.config.size_len as u32)
|
||||
.context("AU-size")?;
|
||||
|
||||
// Will ensure the size is non-zero after we get the index
|
||||
|
@ -85,12 +72,12 @@ impl<'a> FromBitStreamWith<'a> for AuHeader {
|
|||
|
||||
this.index = match ctx.prev_index {
|
||||
None => r
|
||||
.read::<u32>(ctx.config.index_len as u32)
|
||||
.read_var::<u32>(ctx.config.index_len as u32)
|
||||
.context("AU-Index")?
|
||||
.into(),
|
||||
Some(prev_index) => {
|
||||
let delta = r
|
||||
.read::<u32>(ctx.config.index_delta_len as u32)
|
||||
.read_var::<u32>(ctx.config.index_delta_len as u32)
|
||||
.context("AU-Index-delta")?;
|
||||
if delta > 0 {
|
||||
this.is_interleaved = true;
|
||||
|
@ -112,17 +99,15 @@ impl<'a> FromBitStreamWith<'a> for AuHeader {
|
|||
}
|
||||
|
||||
let delta = r
|
||||
.read::<u32>(ctx.config.cts_delta_len as u32)
|
||||
.read_var::<i32>(ctx.config.cts_delta_len as u32)
|
||||
.context("CTS-delta")?;
|
||||
let delta = raw_2_comp_to_i32(delta, ctx.config.cts_delta_len);
|
||||
this.cts_delta = Some(delta);
|
||||
}
|
||||
|
||||
if ctx.config.dts_delta_len > 0 && r.read_bit().context("DTS-flag")? {
|
||||
let delta = r
|
||||
.read::<u32>(ctx.config.dts_delta_len as u32)
|
||||
.read_var::<i32>(ctx.config.dts_delta_len as u32)
|
||||
.context("DTS-delta")?;
|
||||
let delta = raw_2_comp_to_i32(delta, ctx.config.dts_delta_len);
|
||||
this.dts_delta = Some(delta);
|
||||
}
|
||||
|
||||
|
@ -161,13 +146,13 @@ impl<'a> ToBitStreamWith<'a> for AuHeader {
|
|||
Err(ZeroSizedAu(self.index))?;
|
||||
}
|
||||
|
||||
w.write(ctx.config.size_len as u32, size)
|
||||
w.write_var(ctx.config.size_len as u32, size)
|
||||
.context("AU-size")?;
|
||||
}
|
||||
|
||||
match ctx.prev_index {
|
||||
None => w
|
||||
.write(ctx.config.index_len as u32, *self.index)
|
||||
.write_var(ctx.config.index_len as u32, *self.index)
|
||||
.context("AU-Index")?,
|
||||
Some(prev_index) => {
|
||||
let index_delta = self
|
||||
|
@ -179,7 +164,7 @@ impl<'a> ToBitStreamWith<'a> for AuHeader {
|
|||
prev_index,
|
||||
})
|
||||
.context("AU-Index-delta")?;
|
||||
w.write(ctx.config.index_delta_len as u32, index_delta)
|
||||
w.write_var(ctx.config.index_delta_len as u32, index_delta)
|
||||
.context("AU-Index-delta")?;
|
||||
}
|
||||
}
|
||||
|
@ -191,16 +176,8 @@ impl<'a> ToBitStreamWith<'a> for AuHeader {
|
|||
if ctx.prev_index.is_none() {
|
||||
w.write_bit(false).context("CTS-flag")?;
|
||||
} else if let Some(cts_delta) = self.cts_delta {
|
||||
let Some(cts_delta) = mask_valid_2_comp(cts_delta, ctx.config.cts_delta_len) else {
|
||||
return Err(OutOfRangeSizeCtsDelta {
|
||||
cts_delta,
|
||||
index: self.index,
|
||||
}
|
||||
.into());
|
||||
};
|
||||
|
||||
w.write_bit(true).context("CTS-flag")?;
|
||||
w.write(ctx.config.cts_delta_len as u32, cts_delta)
|
||||
w.write_var(ctx.config.cts_delta_len as u32, cts_delta)
|
||||
.context("CTS-delta")?;
|
||||
} else {
|
||||
w.write_bit(false).context("CTS-flag")?;
|
||||
|
@ -209,16 +186,8 @@ impl<'a> ToBitStreamWith<'a> for AuHeader {
|
|||
|
||||
if ctx.config.dts_delta_len > 0 {
|
||||
if let Some(dts_delta) = self.dts_delta {
|
||||
let Some(dts_delta) = mask_valid_2_comp(dts_delta, ctx.config.dts_delta_len) else {
|
||||
return Err(OutOfRangeSizeDtsDelta {
|
||||
dts_delta,
|
||||
index: self.index,
|
||||
}
|
||||
.into());
|
||||
};
|
||||
|
||||
w.write_bit(true).context("DTS-flag")?;
|
||||
w.write(ctx.config.dts_delta_len as u32, dts_delta)
|
||||
w.write_var(ctx.config.dts_delta_len as u32, dts_delta)
|
||||
.context("DTS-delta")?;
|
||||
} else {
|
||||
w.write_bit(false).context("DTS-flag")?;
|
||||
|
|
|
@ -722,7 +722,7 @@ impl RtpMpeg4GenericPay {
|
|||
let mut res = w.build_with(&header, &ctx);
|
||||
if res.is_ok() {
|
||||
// add final padding
|
||||
res = w.write(7, 0).map_err(Into::into);
|
||||
res = w.write::<7, u8>(0).map_err(Into::into);
|
||||
}
|
||||
if let Err(err) = res {
|
||||
gst::error!(
|
||||
|
@ -913,7 +913,7 @@ impl RtpMpeg4GenericPay {
|
|||
}
|
||||
|
||||
// add final padding
|
||||
if let Err(err) = w.write(7, 0) {
|
||||
if let Err(err) = w.write::<7, u8>(0) {
|
||||
gst::error!(
|
||||
CAT,
|
||||
imp = self,
|
||||
|
|
|
@ -10,54 +10,6 @@ pub fn seqnum_distance(seqnum1: u16, seqnum2: u16) -> i16 {
|
|||
seqnum1.wrapping_sub(seqnum2)
|
||||
}
|
||||
|
||||
/// Converts a raw two's complement value of len `bit_len` into an i32.
|
||||
///
|
||||
/// # Panic
|
||||
///
|
||||
/// Panics if `bit_len` > 32.
|
||||
#[inline]
|
||||
pub fn raw_2_comp_to_i32(val: u32, bit_len: u8) -> i32 {
|
||||
assert!(bit_len <= 32);
|
||||
|
||||
if val < 1u32 << (bit_len - 1) as u32 {
|
||||
// val is positive
|
||||
val as i32
|
||||
} else {
|
||||
((0x1_0000_0000 - (1u64 << bit_len)) as u32 + val) as i32
|
||||
}
|
||||
}
|
||||
|
||||
/// Masks the provided `i32` value to be used as a two's complement of len `bit_len`,
|
||||
/// so the resulting value can be passed to APIs which check the bit range.
|
||||
///
|
||||
/// Returns `None` the `i32` value exceeds the range of a two's complement
|
||||
/// of len `bit_len`.
|
||||
///
|
||||
/// # Panic
|
||||
///
|
||||
/// Panics if `bit_len` > 32.
|
||||
#[inline]
|
||||
pub fn mask_valid_2_comp(val: i32, bit_len: u8) -> Option<i32> {
|
||||
let bit_len = bit_len as u32;
|
||||
|
||||
if bit_len == i32::BITS {
|
||||
return Some(val);
|
||||
}
|
||||
|
||||
assert!(bit_len < i32::BITS);
|
||||
|
||||
let overhead = i32::BITS - bit_len;
|
||||
|
||||
let leading_zeros = val.leading_zeros();
|
||||
if leading_zeros > 0 && leading_zeros < overhead
|
||||
|| leading_zeros == 0 && val.leading_ones() < overhead
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(((1 << bit_len) - 1) & val)
|
||||
}
|
||||
|
||||
/// Defines a comparable new type `$typ` on a `[std::num::Wrapping]::<u32>`.
|
||||
///
|
||||
/// The new type will wrap-around on additions and substractions and it comparison
|
||||
|
@ -431,70 +383,6 @@ mod tests {
|
|||
assert_eq!(seqnum_distance(0, 0x8000), -0x8000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn raw_2_comp_12bits_to_i32() {
|
||||
const BITS: u8 = 12;
|
||||
assert_eq!(raw_2_comp_to_i32(0, BITS), 0);
|
||||
assert_eq!(raw_2_comp_to_i32(1, BITS), 1);
|
||||
assert_eq!(raw_2_comp_to_i32(2, BITS), 2);
|
||||
assert_eq!(raw_2_comp_to_i32(0xfff, BITS), -1i16 as i32);
|
||||
assert_eq!(raw_2_comp_to_i32(0xffe, BITS), -2i16 as i32);
|
||||
assert_eq!(raw_2_comp_to_i32(0x7ff, BITS), (1 << (BITS - 1)) - 1);
|
||||
assert_eq!(raw_2_comp_to_i32(0x800, BITS), -(1 << (BITS - 1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn raw_2_comp_16bits_to_i32() {
|
||||
const BITS: u8 = i16::BITS as u8;
|
||||
assert_eq!(raw_2_comp_to_i32(0, BITS), 0);
|
||||
assert_eq!(raw_2_comp_to_i32(1, BITS), 1);
|
||||
assert_eq!(raw_2_comp_to_i32(2, BITS), 2);
|
||||
assert_eq!(raw_2_comp_to_i32(0xffff, BITS), -1i16 as i32);
|
||||
assert_eq!(raw_2_comp_to_i32(0xfffe, BITS), -2i16 as i32);
|
||||
assert_eq!(raw_2_comp_to_i32(0x7fff, BITS), i16::MAX as i32);
|
||||
assert_eq!(raw_2_comp_to_i32(0x8000, BITS), i16::MIN as i32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn raw_2_comp_32bits_to_i32() {
|
||||
const BITS: u8 = i32::BITS as u8;
|
||||
assert_eq!(raw_2_comp_to_i32(0, BITS), 0);
|
||||
assert_eq!(raw_2_comp_to_i32(1, BITS), 1);
|
||||
assert_eq!(raw_2_comp_to_i32(2, BITS), 2);
|
||||
assert_eq!(raw_2_comp_to_i32(0xffff_ffff, BITS), -1i16 as i32);
|
||||
assert_eq!(raw_2_comp_to_i32(0xffff_fffe, BITS), -2i16 as i32);
|
||||
assert_eq!(raw_2_comp_to_i32(0x7fff_ffff, BITS), i32::MAX);
|
||||
assert_eq!(raw_2_comp_to_i32(0x8000_0000, BITS), i32::MIN);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mask_valid_2_comp_ok() {
|
||||
const BITS: u8 = i32::BITS as u8;
|
||||
assert_eq!(mask_valid_2_comp(0, BITS), Some(0));
|
||||
assert_eq!(mask_valid_2_comp(-1, BITS), Some(-1));
|
||||
assert_eq!(mask_valid_2_comp(i32::MIN, BITS), Some(i32::MIN));
|
||||
assert_eq!(mask_valid_2_comp(i32::MAX, BITS), Some(i32::MAX));
|
||||
|
||||
assert_eq!(mask_valid_2_comp(0, 6), Some(0));
|
||||
assert_eq!(mask_valid_2_comp(0x2f, 6), Some(0x2f)); // -1i6
|
||||
assert_eq!(mask_valid_2_comp(0x20, 6), Some(0x20)); // i6::MIN
|
||||
assert_eq!(mask_valid_2_comp(0x1f, 6), Some(0x1f)); // i6::MAX
|
||||
assert_eq!(mask_valid_2_comp(0x1f, 5), Some(0x1f)); // i6::MAX => -1i5
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mask_valid_2_comp_ko() {
|
||||
const BITS: u8 = i32::BITS as u8;
|
||||
assert_eq!(mask_valid_2_comp(0, BITS), Some(0));
|
||||
assert_eq!(mask_valid_2_comp(-1, BITS), Some(-1));
|
||||
assert_eq!(mask_valid_2_comp(i32::MIN, BITS), Some(i32::MIN));
|
||||
assert_eq!(mask_valid_2_comp(i32::MAX, BITS), Some(i32::MAX));
|
||||
|
||||
assert_eq!(mask_valid_2_comp(0, 5), Some(0));
|
||||
assert!(mask_valid_2_comp(0x2f, 5).is_none()); // -1i6
|
||||
assert!(mask_valid_2_comp(0x20, 5).is_none()); // i6::MIN
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrapping_u32_basics() {
|
||||
let zero = MyWrapper::ZERO;
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use bitstream_io::{BigEndian, BitQueue, BitRead, Endianness};
|
||||
use std::io;
|
||||
use bitstream_io::{BigEndian, BitRead, Endianness, UnsignedInteger as _};
|
||||
use std::{io, mem};
|
||||
|
||||
/// Implementation of the bool decoder from RFC 6386:
|
||||
/// https://datatracker.ietf.org/doc/html/rfc6386#section-7.3
|
||||
|
@ -112,66 +112,69 @@ impl<R: io::Read> BitRead for BoolDecoder<R> {
|
|||
self.next_bit()
|
||||
}
|
||||
|
||||
fn read<U>(&mut self, mut bits: u32) -> std::io::Result<U>
|
||||
fn read_unsigned_counted<const MAX: u32, U>(
|
||||
&mut self,
|
||||
bits: bitstream_io::BitCount<MAX>,
|
||||
) -> io::Result<U>
|
||||
where
|
||||
U: bitstream_io::Numeric,
|
||||
U: bitstream_io::UnsignedInteger,
|
||||
{
|
||||
if bits > U::BITS_SIZE {
|
||||
let mut bits = u32::from(bits);
|
||||
if bits > MAX || bits > mem::size_of::<U>() as u32 * 8 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"excessive bits for type read",
|
||||
));
|
||||
}
|
||||
|
||||
let mut queue = BitQueue::<BigEndian, U>::new();
|
||||
let mut v = U::ZERO;
|
||||
|
||||
while bits > 0 {
|
||||
queue.push(1, U::from_u8(self.next_bit()? as u8));
|
||||
v = v << 1 | U::from_u8(self.next_bit()? as u8);
|
||||
bits -= 1;
|
||||
}
|
||||
|
||||
Ok(queue.value())
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
fn read_signed<S>(&mut self, bits: u32) -> std::io::Result<S>
|
||||
fn read_signed_counted<const MAX: u32, S>(
|
||||
&mut self,
|
||||
bits: bitstream_io::BitCount<MAX>,
|
||||
) -> io::Result<S>
|
||||
where
|
||||
S: bitstream_io::SignedNumeric,
|
||||
S: bitstream_io::SignedInteger,
|
||||
{
|
||||
BigEndian::read_signed(self, bits)
|
||||
let sign = self.next_bit()?;
|
||||
let v = self.read_unsigned_counted::<MAX, S::Unsigned>(
|
||||
bits.checked_sub::<MAX>(1).ok_or(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"signed reads need at least 1 bit for sign",
|
||||
))?,
|
||||
)?;
|
||||
Ok(if sign {
|
||||
v.as_negative(bits.into())
|
||||
} else {
|
||||
v.as_non_negative()
|
||||
})
|
||||
}
|
||||
|
||||
fn read_signed_in<const BITS: u32, S>(&mut self) -> std::io::Result<S>
|
||||
where
|
||||
S: bitstream_io::SignedNumeric,
|
||||
{
|
||||
BigEndian::read_signed(self, BITS)
|
||||
}
|
||||
|
||||
fn read_to<V>(&mut self) -> std::io::Result<V>
|
||||
fn read_to<V>(&mut self) -> io::Result<V>
|
||||
where
|
||||
V: bitstream_io::Primitive,
|
||||
{
|
||||
BigEndian::read_primitive(self)
|
||||
}
|
||||
|
||||
fn read_as_to<F, V>(&mut self) -> std::io::Result<V>
|
||||
fn read_as_to<F, V>(&mut self) -> io::Result<V>
|
||||
where
|
||||
F: bitstream_io::Endianness,
|
||||
F: Endianness,
|
||||
V: bitstream_io::Primitive,
|
||||
{
|
||||
F::read_primitive(self)
|
||||
}
|
||||
|
||||
fn skip(&mut self, mut bits: u32) -> std::io::Result<()> {
|
||||
while bits > 0 {
|
||||
self.next_bit()?;
|
||||
bits -= 1;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn byte_aligned(&self) -> bool {
|
||||
false
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn byte_align(&mut self) {
|
||||
|
|
|
@ -104,7 +104,7 @@ trait BitReadExt: BitRead {
|
|||
// `as_negative()` that works with absolute value + sign instead of two's complement.
|
||||
fn read_with_sign(&mut self, bits: u32) -> Result<i8, io::Error> {
|
||||
assert!(bits > 0 && bits <= 7);
|
||||
let value = self.read::<u8>(bits)?;
|
||||
let value = self.read_var::<u8>(bits)?;
|
||||
let sign = self.read_bit()?;
|
||||
|
||||
if sign {
|
||||
|
@ -133,8 +133,8 @@ impl FromBitStreamWith<'_> for FrameHeader {
|
|||
// that is read here is 50:50 so it's equivalent to no encoding at all.
|
||||
let (color_space, clamping_type) = if *keyframe {
|
||||
(
|
||||
Some(r.read::<u8>(1).context("color_space")?),
|
||||
Some(r.read::<u8>(1).context("clamping_type")?),
|
||||
Some(r.read::<1, u8>().context("color_space")?),
|
||||
Some(r.read::<1, u8>().context("clamping_type")?),
|
||||
)
|
||||
} else {
|
||||
(None, None)
|
||||
|
@ -150,9 +150,9 @@ impl FromBitStreamWith<'_> for FrameHeader {
|
|||
None
|
||||
};
|
||||
|
||||
let filter_type = r.read::<u8>(1).context("filter_type")?;
|
||||
let loop_filter_level = r.read::<u8>(6).context("loop_filter_level")?;
|
||||
let sharpness_level = r.read::<u8>(3).context("sharpness_level")?;
|
||||
let filter_type = r.read::<1, u8>().context("filter_type")?;
|
||||
let loop_filter_level = r.read::<6, u8>().context("loop_filter_level")?;
|
||||
let sharpness_level = r.read::<3, u8>().context("sharpness_level")?;
|
||||
|
||||
let loop_filter_adj_enable = r.read_bit().context("loop_filter_adj_enable")?;
|
||||
|
||||
|
@ -162,7 +162,7 @@ impl FromBitStreamWith<'_> for FrameHeader {
|
|||
None
|
||||
};
|
||||
|
||||
let nbr_of_dct_partitions = 1 << r.read::<u8>(2).context("nbr_of_dct_partitions")?;
|
||||
let nbr_of_dct_partitions = 1 << r.read::<2, u8>().context("nbr_of_dct_partitions")?;
|
||||
|
||||
Ok(FrameHeader {
|
||||
color_space,
|
||||
|
@ -234,7 +234,7 @@ impl FromBitStream for SegmentFeatureData {
|
|||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let segment_feature_mode = r.read::<u8>(1).context("segment_feature_mode")?;
|
||||
let segment_feature_mode = r.read::<1, u8>().context("segment_feature_mode")?;
|
||||
|
||||
let mut quantizer_update = SmallVec::new();
|
||||
let mut loop_filter_update = SmallVec::new();
|
||||
|
@ -283,7 +283,7 @@ impl FromBitStream for MbSegmentationMap {
|
|||
let segment_prob_update = r.read_bit().context("segment_prob_update")?;
|
||||
|
||||
if segment_prob_update {
|
||||
let segment_prob = r.read::<u8>(8).context("segment_prob")?;
|
||||
let segment_prob = r.read::<8, u8>().context("segment_prob")?;
|
||||
|
||||
segment_probs.push(Some(segment_prob));
|
||||
} else {
|
||||
|
|
|
@ -31,13 +31,13 @@ impl FromBitStream for FrameHeader {
|
|||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let marker = r.read::<u8>(2).context("frame_marker")?;
|
||||
let marker = r.read::<2, u8>().context("frame_marker")?;
|
||||
if marker != 2 {
|
||||
bail!("Wrong frame marker");
|
||||
}
|
||||
|
||||
let profile_low_bit = r.read::<u8>(1).context("profile_low_bit")?;
|
||||
let profile_high_bit = r.read::<u8>(1).context("profile_high_bit")?;
|
||||
let profile_low_bit = r.read::<1, u8>().context("profile_low_bit")?;
|
||||
let profile_high_bit = r.read::<1, u8>().context("profile_high_bit")?;
|
||||
|
||||
let profile = (profile_high_bit << 1) | profile_low_bit;
|
||||
if profile == 3 {
|
||||
|
@ -131,8 +131,10 @@ impl FromBitStreamWith<'_> for KeyframeInfo {
|
|||
frame_height_minus_1 as u32 + 1,
|
||||
);
|
||||
|
||||
let render_and_frame_size_different =
|
||||
r.read::<u8>(1).context("render_and_frame_size_different")? == 1;
|
||||
let render_and_frame_size_different = r
|
||||
.read::<1, u8>()
|
||||
.context("render_and_frame_size_different")?
|
||||
== 1;
|
||||
|
||||
let render_size = if render_and_frame_size_different {
|
||||
let render_width_minus_1 = r.read_to::<u16>().context("render_width_minus_1")?;
|
||||
|
@ -199,13 +201,13 @@ impl FromBitStreamWith<'_> for ColorConfig {
|
|||
8
|
||||
};
|
||||
|
||||
let color_space = r.read::<u8>(3).context("color_space")?;
|
||||
let color_space = r.read::<3, u8>().context("color_space")?;
|
||||
let (color_range, sub_sampling_x, sub_sampling_y) = if color_space != CS_RGB {
|
||||
let color_range = r.read::<u8>(1).context("color_range")?;
|
||||
let color_range = r.read::<1, u8>().context("color_range")?;
|
||||
|
||||
let (sub_sampling_x, sub_sampling_y) = if *profile == 1 || *profile == 3 {
|
||||
let sub_sampling_x = r.read::<u8>(1).context("sub_sampling_x")?;
|
||||
let sub_sampling_y = r.read::<u8>(1).context("sub_sampling_y")?;
|
||||
let sub_sampling_x = r.read::<1, u8>().context("sub_sampling_x")?;
|
||||
let sub_sampling_y = r.read::<1, u8>().context("sub_sampling_y")?;
|
||||
r.skip(1).context("reserved_zero")?;
|
||||
|
||||
(sub_sampling_x, sub_sampling_y)
|
||||
|
|
|
@ -28,7 +28,7 @@ gst-base = { workspace = true, features = ["v1_22"]}
|
|||
gst-video = { workspace = true, features = ["v1_16"]}
|
||||
winnow = "0.7"
|
||||
smallvec = "1"
|
||||
bitstream-io = "2.3"
|
||||
bitstream-io = "3"
|
||||
itertools = "0.14"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -29,24 +29,24 @@ impl AncDataHeader {
|
|||
|
||||
let mut r = BitReader::endian(Cursor::new(slice), BigEndian);
|
||||
|
||||
let zeroes = r.read::<u8>(6).context("zero bits")?;
|
||||
let zeroes = r.read::<6, u8>().context("zero bits")?;
|
||||
if zeroes != 0 {
|
||||
anyhow::bail!("Zero bits not zero!");
|
||||
}
|
||||
let c_not_y_channel_flag = r.read_bit().context("c_not_y_channel_flag")?;
|
||||
let line_number = r.read::<u16>(11).context("line number")?;
|
||||
let horizontal_offset = r.read::<u16>(12).context("horizontal offset")?;
|
||||
let line_number = r.read::<11, u16>().context("line number")?;
|
||||
let horizontal_offset = r.read::<12, u16>().context("horizontal offset")?;
|
||||
// Top two bits are parity bits and can be stripped off
|
||||
let did = (r.read::<u16>(10).context("DID")? & 0xff) as u8;
|
||||
let sdid = (r.read::<u16>(10).context("SDID")? & 0xff) as u8;
|
||||
let data_count = (r.read::<u16>(10).context("data count")? & 0xff) as u8;
|
||||
let did = (r.read::<10, u16>().context("DID")? & 0xff) as u8;
|
||||
let sdid = (r.read::<10, u16>().context("SDID")? & 0xff) as u8;
|
||||
let data_count = (r.read::<10, u16>().context("data count")? & 0xff) as u8;
|
||||
|
||||
r.skip(data_count as u32 * 10).context("data")?;
|
||||
|
||||
let checksum = r.read::<u16>(10).context("checksum")?;
|
||||
let checksum = r.read::<10, u16>().context("checksum")?;
|
||||
|
||||
while !r.byte_aligned() {
|
||||
let one = r.read::<u8>(1).context("alignment")?;
|
||||
let one = r.read::<1, u8>().context("alignment")?;
|
||||
if one != 1 {
|
||||
anyhow::bail!("Alignment bits are not ones!");
|
||||
}
|
||||
|
@ -104,33 +104,33 @@ pub(crate) fn convert_to_st2038_buffer(
|
|||
|
||||
let mut w = BitWriter::endian(&mut output, BigEndian);
|
||||
|
||||
w.write::<u8>(6, 0b00_0000).context("zero bits")?;
|
||||
w.write::<6, u8>(0b00_0000).context("zero bits")?;
|
||||
w.write_bit(c_not_y_channel).context("c_not_y_channel")?;
|
||||
w.write::<u16>(11, line_number).context("line number")?;
|
||||
w.write::<u16>(12, horizontal_offset)
|
||||
w.write::<11, u16>(line_number).context("line number")?;
|
||||
w.write::<12, u16>(horizontal_offset)
|
||||
.context("horizontal offset")?;
|
||||
|
||||
let mut checksum = 0u16;
|
||||
|
||||
w.write::<u16>(10, extend_with_even_odd_parity(did, &mut checksum))
|
||||
w.write::<10, u16>(extend_with_even_odd_parity(did, &mut checksum))
|
||||
.context("DID")?;
|
||||
w.write::<u16>(10, extend_with_even_odd_parity(sdid, &mut checksum))
|
||||
w.write::<10, u16>(extend_with_even_odd_parity(sdid, &mut checksum))
|
||||
.context("SDID")?;
|
||||
w.write::<u16>(
|
||||
10,
|
||||
extend_with_even_odd_parity(payload.len() as u8, &mut checksum),
|
||||
)
|
||||
w.write::<10, u16>(extend_with_even_odd_parity(
|
||||
payload.len() as u8,
|
||||
&mut checksum,
|
||||
))
|
||||
.context("data count")?;
|
||||
|
||||
for &b in payload {
|
||||
w.write::<u16>(10, extend_with_even_odd_parity(b, &mut checksum))
|
||||
w.write::<10, u16>(extend_with_even_odd_parity(b, &mut checksum))
|
||||
.context("payload")?;
|
||||
}
|
||||
|
||||
checksum &= 0x1_ff;
|
||||
checksum |= ((!(checksum >> 8)) & 0x0_01) << 9;
|
||||
|
||||
w.write::<u16>(10, checksum).context("checksum")?;
|
||||
w.write::<10, u16>(checksum).context("checksum")?;
|
||||
|
||||
while !w.byte_aligned() {
|
||||
w.write_bit(true).context("padding")?;
|
||||
|
|
|
@ -179,7 +179,7 @@ impl St2038AncToCc {
|
|||
|
||||
// Convert data from 10 bits to 8 bits
|
||||
for _ in 0..header.data_count {
|
||||
let b = (r.read::<u16>(10).unwrap() & 0xff) as u8;
|
||||
let b = (r.read::<10, u16>().unwrap() & 0xff) as u8;
|
||||
sub_slice[0] = b;
|
||||
sub_slice = &mut sub_slice[1..];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue