1use alloc::vec::Vec;
6
7use super::{J2kEncodeDispatchReport, J2kEncodeStageResult};
8use crate::{
9 EncodedHtJ2kCodeBlock, EncodedHtJ2kCodeBlockSet, EncodedJ2kCodeBlock, J2kForwardDwt53Job,
10 J2kForwardDwt53Output, J2kForwardDwt97Job, J2kForwardDwt97Output, J2kForwardIctJob,
11 J2kForwardRctJob, J2kHtCodeBlockEncodeJob, J2kHtCodeBlockSetEncodeJob, J2kHtSubbandEncodeJob,
12 J2kPacketizationEncodeJob, J2kPacketizationProgressionOrder, J2kQuantizeSubbandJob,
13 J2kResidentHtj2kTileEncodeJob, J2kTier1CodeBlockEncodeJob,
14};
15
16#[derive(Debug, Clone, Copy)]
18pub struct J2kDeinterleaveToF32Job<'a> {
19 pub pixels: &'a [u8],
21 pub num_pixels: usize,
23 pub num_components: u16,
25 pub bit_depth: u8,
27 pub signed: bool,
29}
30
31#[derive(Debug, Clone, Copy)]
35pub struct J2kDeinterleaveMctToF32Job<'a> {
36 pub pixels: &'a [u8],
38 pub num_pixels: usize,
40 pub bit_depth: u8,
42 pub signed: bool,
44 pub reversible: bool,
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub struct J2kEncodeContext {
51 pub num_pixels: usize,
53 pub num_components: u16,
55 pub bit_depth: u8,
57 pub signed: bool,
59 pub reversible: bool,
61}
62
63#[derive(Debug, Clone, Copy)]
65pub struct J2kHtj2kTileEncodeJob<'a> {
66 pub pixels: &'a [u8],
68 pub width: u32,
70 pub height: u32,
72 pub num_components: u16,
74 pub bit_depth: u8,
76 pub signed: bool,
78 pub num_decomposition_levels: u8,
80 pub reversible: bool,
82 pub use_mct: bool,
84 pub guard_bits: u8,
86 pub code_block_width: u32,
88 pub code_block_height: u32,
90 pub progression_order: J2kPacketizationProgressionOrder,
92 pub component_sampling: &'a [(u8, u8)],
94 pub quantization_steps: &'a [(u16, u16)],
96}
97
98#[derive(Debug, Default, Clone, Copy)]
100pub struct CpuOnlyJ2kEncodeStageAccelerator;
101
102pub trait J2kEncodeStageAccelerator {
104 fn begin_encode(&mut self, _context: J2kEncodeContext) -> J2kEncodeStageResult<()> {
106 Ok(())
107 }
108
109 fn dispatch_report(&self) -> J2kEncodeDispatchReport {
111 J2kEncodeDispatchReport::default()
112 }
113
114 fn ht_subband_maximum_cleanup_magnitude(&self) -> Option<u64> {
116 None
117 }
118
119 fn ht_tile_required_magnitude_bound(&self) -> Option<u8> {
121 None
122 }
123
124 fn encode_deinterleave(
126 &mut self,
127 _job: J2kDeinterleaveToF32Job<'_>,
128 ) -> J2kEncodeStageResult<Option<Vec<Vec<f32>>>> {
129 Ok(None)
130 }
131
132 fn encode_deinterleave_mct(
134 &mut self,
135 _job: J2kDeinterleaveMctToF32Job<'_>,
136 ) -> J2kEncodeStageResult<Option<Vec<Vec<f32>>>> {
137 Ok(None)
138 }
139
140 fn encode_forward_rct(&mut self, _job: J2kForwardRctJob<'_>) -> J2kEncodeStageResult<bool> {
142 Ok(false)
143 }
144
145 fn encode_forward_ict(&mut self, _job: J2kForwardIctJob<'_>) -> J2kEncodeStageResult<bool> {
147 Ok(false)
148 }
149
150 fn encode_forward_dwt53(
152 &mut self,
153 _job: J2kForwardDwt53Job<'_>,
154 ) -> J2kEncodeStageResult<Option<J2kForwardDwt53Output>> {
155 Ok(None)
156 }
157
158 fn encode_forward_dwt53_at_origin(
164 &mut self,
165 job: J2kForwardDwt53Job<'_>,
166 origin: (u32, u32),
167 ) -> J2kEncodeStageResult<Option<J2kForwardDwt53Output>> {
168 if zero_origin_dwt_phase(origin, job.num_levels) {
169 self.encode_forward_dwt53(job)
170 } else {
171 Ok(None)
172 }
173 }
174
175 fn encode_forward_dwt97(
177 &mut self,
178 _job: J2kForwardDwt97Job<'_>,
179 ) -> J2kEncodeStageResult<Option<J2kForwardDwt97Output>> {
180 Ok(None)
181 }
182
183 fn encode_forward_dwt97_at_origin(
186 &mut self,
187 job: J2kForwardDwt97Job<'_>,
188 origin: (u32, u32),
189 ) -> J2kEncodeStageResult<Option<J2kForwardDwt97Output>> {
190 if zero_origin_dwt_phase(origin, job.num_levels) {
191 self.encode_forward_dwt97(job)
192 } else {
193 Ok(None)
194 }
195 }
196
197 fn encode_quantize_subband(
199 &mut self,
200 _job: J2kQuantizeSubbandJob<'_>,
201 ) -> J2kEncodeStageResult<Option<Vec<i32>>> {
202 Ok(None)
203 }
204
205 fn encode_tier1_code_block(
207 &mut self,
208 _job: J2kTier1CodeBlockEncodeJob<'_>,
209 ) -> J2kEncodeStageResult<Option<EncodedJ2kCodeBlock>> {
210 Ok(None)
211 }
212
213 fn encode_tier1_code_blocks(
215 &mut self,
216 _jobs: &[J2kTier1CodeBlockEncodeJob<'_>],
217 ) -> J2kEncodeStageResult<Option<Vec<EncodedJ2kCodeBlock>>> {
218 Ok(None)
219 }
220
221 fn encode_ht_code_block(
223 &mut self,
224 _job: J2kHtCodeBlockEncodeJob<'_>,
225 ) -> J2kEncodeStageResult<Option<EncodedHtJ2kCodeBlock>> {
226 Ok(None)
227 }
228
229 fn encode_ht_code_blocks(
231 &mut self,
232 _jobs: &[J2kHtCodeBlockEncodeJob<'_>],
233 ) -> J2kEncodeStageResult<Option<Vec<EncodedHtJ2kCodeBlock>>> {
234 Ok(None)
235 }
236
237 #[doc(hidden)]
239 fn encode_ht_code_block_sets(
240 &mut self,
241 _jobs: &[J2kHtCodeBlockSetEncodeJob<'_>],
242 ) -> J2kEncodeStageResult<Option<Vec<EncodedHtJ2kCodeBlockSet>>> {
243 Ok(None)
244 }
245
246 fn encode_ht_subband(
248 &mut self,
249 _job: J2kHtSubbandEncodeJob<'_>,
250 ) -> J2kEncodeStageResult<Option<Vec<EncodedHtJ2kCodeBlock>>> {
251 Ok(None)
252 }
253
254 fn encode_htj2k_tile(
256 &mut self,
257 _job: J2kHtj2kTileEncodeJob<'_>,
258 ) -> J2kEncodeStageResult<Option<Vec<u8>>> {
259 Ok(None)
260 }
261
262 fn encode_resident_htj2k_tile(
264 &mut self,
265 _job: J2kResidentHtj2kTileEncodeJob<'_>,
266 ) -> J2kEncodeStageResult<Option<Vec<u8>>> {
267 Ok(None)
268 }
269
270 fn prefer_parallel_cpu_code_block_fallback(&self) -> bool {
272 false
273 }
274
275 fn prefer_parallel_cpu_tile_encode(&self) -> bool {
277 false
278 }
279
280 fn declines_every_stage(&self) -> bool {
286 false
287 }
288
289 fn encode_packetization(
291 &mut self,
292 _job: J2kPacketizationEncodeJob<'_>,
293 ) -> J2kEncodeStageResult<Option<Vec<u8>>> {
294 Ok(None)
295 }
296}
297
298#[doc(hidden)]
299impl J2kEncodeStageAccelerator for CpuOnlyJ2kEncodeStageAccelerator {
300 fn prefer_parallel_cpu_code_block_fallback(&self) -> bool {
301 true
302 }
303
304 fn prefer_parallel_cpu_tile_encode(&self) -> bool {
305 true
306 }
307
308 fn declines_every_stage(&self) -> bool {
309 true
310 }
311}
312
313fn zero_origin_dwt_phase(origin: (u32, u32), levels: u8) -> bool {
314 1_u64.checked_shl(u32::from(levels)).is_some_and(|scale| {
315 u64::from(origin.0).is_multiple_of(scale) && u64::from(origin.1).is_multiple_of(scale)
316 })
317}
318
319#[cfg(test)]
320mod tests {
321 use super::{CpuOnlyJ2kEncodeStageAccelerator, J2kEncodeStageAccelerator};
322 use crate::J2kHtCodeBlockSetEncodeJob;
323
324 #[test]
325 fn legacy_accelerators_decline_explicit_ht_sets_by_default() {
326 let coefficients = [7_i32];
327 let jobs = [J2kHtCodeBlockSetEncodeJob {
328 coefficients: &coefficients,
329 width: 1,
330 height: 1,
331 total_bitplanes: 3,
332 cleanup_bitplane: 1,
333 target_coding_passes: 3,
334 }];
335 let mut accelerator = CpuOnlyJ2kEncodeStageAccelerator;
336
337 assert!(accelerator
338 .encode_ht_code_block_sets(&jobs)
339 .expect("default set hook")
340 .is_none());
341 }
342}