···416416 end
417417 end
418418419419-(** Decode a CCSDS block. Returns an array of residuals (including position 0
420420- for the reference if [is_ref]). Also returns the reconstructed reference
421421- sample via side effect on [ref_out]. *)
422422-let decode_ccsds_block br block_size bps id_len is_ref =
419419+(** Decode one or more CCSDS blocks. Writes residuals into [out] starting at
420420+ [out_pos]. [is_ref] indicates whether the first decoded block starts an RSI.
421421+ Returns the number of blocks decoded (>1 only for aggregated zero blocks).
422422+*)
423423+let decode_ccsds_blocks br block_size bps id_len is_ref out out_pos
424424+ blocks_remaining =
423425 let id = Bitreader.read_bits br id_len in
424426 let max_id = (1 lsl id_len) - 1 in
425427 if id = 0 then begin
···428430 if sub = 0 then begin
429431 (* Zero block *)
430432 let ref_sample = if is_ref then Bitreader.read_bits br bps else 0 in
431431- (* Read FS for zero block count (we only use 1 with rsi=block_size) *)
432432- let _zero_count = Bitreader.read_unary br in
433433- let residuals = Array.make block_size 0 in
434434- (* All residuals are 0; reference goes in position 0 if is_ref *)
435435- if is_ref then residuals.(0) <- ref_sample;
436436- (residuals, ref_sample)
433433+ (* Read FS for zero block count *)
434434+ let fs = Bitreader.read_unary br in
435435+ let zero_blocks = fs + 1 in
436436+ (* If zero_blocks >= 5 (ROS encoding), adjust *)
437437+ let zero_blocks =
438438+ if zero_blocks = 5 then blocks_remaining (* rest of segment *)
439439+ else if zero_blocks > 5 then zero_blocks - 1
440440+ else zero_blocks
441441+ in
442442+ let zero_blocks = min zero_blocks blocks_remaining in
443443+ (* Fill zero blocks: first block may have reference *)
444444+ if is_ref then out.(out_pos) <- ref_sample;
445445+ (* All other positions in all zero blocks are already 0 (from Array.make)
446446+ but let's be explicit for blocks beyond the first *)
447447+ let total_samples = zero_blocks * block_size in
448448+ for i = 0 to total_samples - 1 do
449449+ if not (is_ref && i = 0) then out.(out_pos + i) <- 0
450450+ done;
451451+ zero_blocks
437452 end
438453 else begin
439454 (* Second extension *)
440455 let ref_sample = if is_ref then Bitreader.read_bits br bps else 0 in
441441- let residuals = Array.make block_size 0 in
442442- if is_ref then residuals.(0) <- ref_sample;
456456+ if is_ref then out.(out_pos) <- ref_sample;
443457 let count = if is_ref then block_size - 1 else block_size in
444444- let res_ofs = if is_ref then 1 else 0 in
458458+ let res_ofs = out_pos + if is_ref then 1 else 0 in
445459 (* Decode pairs *)
446460 let i = ref 0 in
447461 while !i < count do
···453467 done;
454468 let b = fs_val - (!d * (!d + 1) / 2) in
455469 let a = !d - b in
456456- residuals.(res_ofs + !i) <- a;
457457- if !i + 1 < count then residuals.(res_ofs + !i + 1) <- b;
470470+ out.(res_ofs + !i) <- a;
471471+ if !i + 1 < count then out.(res_ofs + !i + 1) <- b;
458472 i := !i + 2
459473 done;
460460- (residuals, ref_sample)
474474+ 1
461475 end
462476 end
463477 else if id = max_id then begin
464478 (* Uncompressed *)
465479 let ref_sample = if is_ref then Bitreader.read_bits br bps else 0 in
466466- let residuals = Array.make block_size 0 in
467467- if is_ref then residuals.(0) <- ref_sample;
480480+ if is_ref then out.(out_pos) <- ref_sample;
468481 let count = if is_ref then block_size - 1 else block_size in
469469- let res_ofs = if is_ref then 1 else 0 in
482482+ let res_ofs = out_pos + if is_ref then 1 else 0 in
470483 for i = 0 to count - 1 do
471471- residuals.(res_ofs + i) <- Bitreader.read_bits br bps
484484+ out.(res_ofs + i) <- Bitreader.read_bits br bps
472485 done;
473473- (residuals, ref_sample)
486486+ 1
474487 end
475488 else begin
476489 (* Split coding with k = id - 1 *)
477490 let k = id - 1 in
478491 let ref_sample = if is_ref then Bitreader.read_bits br bps else 0 in
479479- let residuals = Array.make block_size 0 in
480480- if is_ref then residuals.(0) <- ref_sample;
492492+ if is_ref then out.(out_pos) <- ref_sample;
481493 let count = if is_ref then block_size - 1 else block_size in
482482- let res_ofs = if is_ref then 1 else 0 in
494494+ let res_ofs = out_pos + if is_ref then 1 else 0 in
483495 for i = 0 to count - 1 do
484496 let q = Bitreader.read_unary br in
485497 let r = if k > 0 then Bitreader.read_bits br k else 0 in
486486- residuals.(res_ofs + i) <- (q lsl k) lor r
498498+ out.(res_ofs + i) <- (q lsl k) lor r
487499 done;
488488- (residuals, ref_sample)
500500+ 1
489501 end
490502491503(* -- Compress ------------------------------------------------------------- *)
···543555 let id_len = id_len_of_bps bps in
544556 let j = cfg.block_size in
545557 let blocks_per_rsi = cfg.rsi in
546546- let n = sample_count in
547547- let all_residuals = Array.make n 0 in
548548- let pos = ref 0 in
549549- let done_ = ref false in
550550- while !pos < n && not !done_ do
558558+ (* Pad to full blocks for decoding *)
559559+ let n_padded = (sample_count + j - 1) / j * j in
560560+ let all_residuals = Array.make n_padded 0 in
561561+ let block_pos = ref 0 in
562562+ (* current block index *)
563563+ let total_blocks = n_padded / j in
564564+ while !block_pos < total_blocks do
551565 (* Decode one RSI *)
552552- for b = 0 to blocks_per_rsi - 1 do
553553- if !pos < n && not !done_ then begin
554554- let is_ref = b = 0 in
555555- if Bitreader.bits_remaining br < id_len + 1 then done_ := true
556556- else begin
557557- let block_len = min j (n - !pos) in
558558- let block, _ref_sample =
559559- decode_ccsds_block br j bps id_len is_ref
560560- in
561561- (* Copy only block_len samples (may be < j for last block) *)
562562- Array.blit block 0 all_residuals !pos block_len;
563563- pos := !pos + block_len
564564- end
566566+ let rsi_start = !block_pos in
567567+ let b = ref 0 in
568568+ while !b < blocks_per_rsi && !block_pos < total_blocks do
569569+ let is_ref = !b = 0 in
570570+ if Bitreader.bits_remaining br < id_len + 1 then
571571+ (* Not enough bits; fill remaining with zeros *)
572572+ block_pos := total_blocks
573573+ else begin
574574+ let out_pos = !block_pos * j in
575575+ let blocks_remaining = blocks_per_rsi - !b in
576576+ let blocks_remaining =
577577+ min blocks_remaining (total_blocks - !block_pos)
578578+ in
579579+ let consumed =
580580+ decode_ccsds_blocks br j bps id_len is_ref all_residuals out_pos
581581+ blocks_remaining
582582+ in
583583+ block_pos := !block_pos + consumed;
584584+ b := !b + consumed
565585 end
566566- done
586586+ done;
587587+ (* If RSI was not fully consumed, advance to next RSI boundary *)
588588+ if !block_pos < rsi_start + blocks_per_rsi && !block_pos < total_blocks
589589+ then block_pos := min total_blocks (rsi_start + blocks_per_rsi)
567590 done;
591591+ (* Truncate to requested sample count *)
592592+ let residuals = Array.sub all_residuals 0 sample_count in
568593 (* Reconstruct samples from residuals *)
569569- let samples = reconstruct_samples cfg all_residuals in
594594+ let samples = reconstruct_samples cfg residuals in
570595 (* Pack samples into output bytes *)
571571- let out = Bytes.make (n * bps_bytes) '\000' in
596596+ let out = Bytes.make (sample_count * bps_bytes) '\000' in
572597 Array.iteri (fun i s -> write_sample out (i * bps_bytes) bps s) samples;
573598 Ok out
574599 with