mirror of
https://github.com/aaru-dps/libaaruformat.git
synced 2026-02-04 05:24:56 +00:00
Use block alignment offset instead of absolute offset
This commit is contained in:
@@ -19,7 +19,7 @@ The flux capture system uses two block types:
|
||||
* `DataStreamPayloadBlock` (`DSPL` / `0x4C505344`): Contains the actual flux data payload (data and index buffers) for individual captures. This is a generic block type that can also be used for other data streams.
|
||||
|
||||
Each flux capture has one entry in the `FluxDataBlock` and one corresponding `DataStreamPayloadBlock` containing its data.
|
||||
The `FluxEntry` structure in the data block contains a `payloadOffset` field that points to the file offset where the corresponding `DataStreamPayloadBlock` is stored.
|
||||
The `FluxEntry` structure in the data block contains a `payloadOffset` field that points to the file offset where the corresponding `DataStreamPayloadBlock` is stored. The offset is stored divided by the block alignment (as indicated by `blockAlignmentShift` in the `FluxHeader`), consistent with DDT table offset storage.
|
||||
|
||||
==== Structure Definition
|
||||
|
||||
@@ -30,6 +30,7 @@ typedef struct FluxHeader
|
||||
{
|
||||
uint32_t identifier; ///< Block identifier, must be BlockType::FluxDataBlock (0x58554C46).
|
||||
uint16_t entries; ///< Number of FluxEntry records following this header.
|
||||
uint8_t blockAlignmentShift; ///< Block alignment shift: 2^blockAlignmentShift = block alignment boundary in bytes.
|
||||
uint64_t crc64; ///< CRC64-ECMA checksum of the FluxEntry array (header excluded).
|
||||
} FluxHeader;
|
||||
|
||||
@@ -52,6 +53,11 @@ typedef struct FluxHeader
|
||||
|entries
|
||||
|The number of flux entry records following this header
|
||||
|
||||
|uint8_t
|
||||
|1 byte
|
||||
|blockAlignmentShift
|
||||
|Block alignment shift: 2^blockAlignmentShift = block alignment boundary in bytes. Used to decode payloadOffset values in FluxEntry structures, which are stored divided by this alignment. Stored in the header to make the block self-contained, similar to DDT headers.
|
||||
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|crc64
|
||||
@@ -121,5 +127,5 @@ typedef struct FluxEntry
|
||||
|uint64_t
|
||||
|8 bytes
|
||||
|payloadOffset
|
||||
|File offset where the DataStreamPayloadBlock containing this capture's data is stored.
|
||||
|Block-aligned file offset where the DataStreamPayloadBlock containing this capture's data is stored, divided by (1 << blockAlignmentShift). To get the absolute file offset, multiply by (1 << blockAlignmentShift) using the blockAlignmentShift value from FluxHeader. This storage method is consistent with DDT table offset storage.
|
||||
|===
|
||||
@@ -103,13 +103,21 @@
|
||||
* data integrity. The identifier field must match BlockType::FluxDataBlock
|
||||
* (0x58554C46, "FLUX" in ASCII).
|
||||
*
|
||||
* The blockAlignmentShift field stores the block alignment shift value used to
|
||||
* decode the payloadOffset values in FluxEntry structures. This makes the block
|
||||
* self-contained, similar to DDT headers, allowing correct decoding of offsets
|
||||
* without requiring access to the main image header.
|
||||
*
|
||||
* @note Only one FluxDataBlock is allowed per image.
|
||||
* @note The entries field is limited to UINT16_MAX (65535) captures per image.
|
||||
* @note The blockAlignmentShift field is stored in the header to support reliable
|
||||
* decoding of payloadOffset values, which are stored divided by (1 << blockAlignmentShift).
|
||||
*/
|
||||
typedef struct FluxHeader
|
||||
{
|
||||
uint32_t identifier; ///< Block identifier, must be BlockType::FluxDataBlock (0x58554C46, "FLUX").
|
||||
uint16_t entries; ///< Number of FluxEntry records following this header. Maximum value: 65535.
|
||||
uint8_t blockAlignmentShift; ///< Block alignment shift: 2^blockAlignmentShift = block alignment boundary in bytes.
|
||||
uint64_t crc64; ///< CRC64-ECMA checksum of the FluxEntry array (header excluded).
|
||||
} FluxHeader;
|
||||
|
||||
@@ -128,9 +136,11 @@ typedef struct FluxHeader
|
||||
*
|
||||
* **Payload Access:**
|
||||
* The payloadOffset field points to the file offset where the corresponding
|
||||
* DataStreamPayloadBlock is stored. The indexOffset field indicates where the index
|
||||
* buffer starts within the payload (the payload is stored as [data_buffer][index_buffer]
|
||||
* concatenated).
|
||||
* DataStreamPayloadBlock is stored. The offset is stored divided by the block alignment
|
||||
* (blockAlignmentShift from FluxHeader), consistent with DDT table offset storage.
|
||||
* To convert to an absolute file offset, multiply by (1 << blockAlignmentShift).
|
||||
* The indexOffset field indicates where the index buffer starts within the payload
|
||||
* (the payload is stored as [data_buffer][index_buffer] concatenated).
|
||||
*
|
||||
* **Resolution:**
|
||||
* Both indexResolution and dataResolution are specified in picoseconds, indicating
|
||||
@@ -151,7 +161,7 @@ typedef struct FluxEntry
|
||||
uint64_t indexResolution; ///< Resolution in picoseconds at which the index stream was sampled.
|
||||
uint64_t dataResolution; ///< Resolution in picoseconds at which the data stream was sampled.
|
||||
uint64_t indexOffset; ///< Byte offset within the payload where the index buffer starts (equals data_length).
|
||||
uint64_t payloadOffset; ///< File offset where the DataStreamPayloadBlock containing this capture's data is stored.
|
||||
uint64_t payloadOffset; ///< Block-aligned file offset where the DataStreamPayloadBlock containing this capture's data is stored, divided by (1 << blockAlignmentShift). To get the absolute offset, multiply by (1 << blockAlignmentShift) from FluxHeader.
|
||||
} FluxEntry;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1073,9 +1073,10 @@ static int32_t extract_flux_data_buffers(const FluxEntry *flux_entry, const uint
|
||||
* This function retrieves the actual flux data and index buffers for a specific
|
||||
* flux capture identified by its head, track, subtrack, and capture_index. The
|
||||
* function locates the corresponding FluxEntry in the flux_entries array (using
|
||||
* the lookup map for efficiency), seeks to the DataStreamPayloadBlock at the specified
|
||||
* payloadOffset, reads and decompresses the payload, validates CRC64 checksums,
|
||||
* and extracts the data and index buffers.
|
||||
* the lookup map for efficiency), converts the payloadOffset (stored divided by block alignment)
|
||||
* to an absolute file offset using blockAlignmentShift from FluxHeader, seeks to the
|
||||
* DataStreamPayloadBlock at the specified offset, reads and decompresses the payload,
|
||||
* validates CRC64 checksums, and extracts the data and index buffers.
|
||||
*
|
||||
* The function supports both uncompressed and LZMA-compressed payload blocks.
|
||||
* CRC64 validation is performed on both the compressed and uncompressed data.
|
||||
@@ -1188,8 +1189,15 @@ AARU_EXPORT int32_t AARU_CALL aaruf_read_flux_capture(void *context, uint32_t he
|
||||
flux_entry->head, flux_entry->track, flux_entry->subtrack, flux_entry->captureIndex,
|
||||
flux_entry->payloadOffset);
|
||||
|
||||
// Get block alignment shift from FluxHeader
|
||||
uint8_t block_alignment_shift = ctx->flux_data_header.blockAlignmentShift;
|
||||
|
||||
// Convert payloadOffset from block-aligned units to absolute file offset
|
||||
// payloadOffset is stored divided by (1 << blockAlignmentShift), consistent with DDT
|
||||
uint64_t absolute_payload_offset = flux_entry->payloadOffset << block_alignment_shift;
|
||||
|
||||
DataStreamPayloadHeader payload_header;
|
||||
int32_t res = read_flux_payload_header(ctx, flux_entry->payloadOffset, &payload_header);
|
||||
int32_t res = read_flux_payload_header(ctx, absolute_payload_offset, &payload_header);
|
||||
if(res != AARUF_STATUS_OK)
|
||||
{
|
||||
TRACE("Exiting aaruf_read_flux_capture() = %d\n", res);
|
||||
|
||||
16
src/close.c
16
src/close.c
@@ -4268,7 +4268,8 @@ static void write_aaru_json_block(aaruformat_context *ctx)
|
||||
* - head, track, subtrack, captureIndex: Identifiers from the record
|
||||
* - dataResolution, indexResolution: Timing resolution metadata
|
||||
* - indexOffset: Offset within payload where index buffer starts (equals data_length)
|
||||
* - payloadOffset: File offset where this payload block was written
|
||||
* - payloadOffset: Block-aligned file offset divided by (1 << blockAlignmentShift),
|
||||
* consistent with DDT offset storage. Multiply by (1 << blockAlignmentShift) to get absolute offset.
|
||||
*
|
||||
* This metadata is later written to the FluxDataBlock to enable efficient lookup
|
||||
* of flux captures by their identifiers.
|
||||
@@ -4338,9 +4339,11 @@ static void write_aaru_json_block(aaruformat_context *ctx)
|
||||
* If compression doesn't reduce size, the raw data is written instead. This
|
||||
* prevents wasting space on incompressible flux data.
|
||||
*
|
||||
* @note The payloadOffset stored in the FluxEntry enables direct seeking to the payload
|
||||
* during reads without requiring a full index scan. This is critical for efficient
|
||||
* random access to flux captures.
|
||||
* @note The payloadOffset stored in the FluxEntry is divided by block alignment
|
||||
* (blockAlignmentShift), consistent with DDT table offset storage. It enables direct
|
||||
* seeking to the payload during reads without requiring a full index scan. This is
|
||||
* critical for efficient random access to flux captures. The blockAlignmentShift
|
||||
* value is stored in the FluxHeader to allow correct decoding.
|
||||
*
|
||||
* @note LZMA properties are written immediately after the header when compression is
|
||||
* enabled. The properties are included in cmpLength but not in the separate
|
||||
@@ -4505,7 +4508,7 @@ static int32_t write_flux_capture_payload(aaruformat_context *ctx, FluxCaptureRe
|
||||
entry->dataResolution = record->entry.dataResolution;
|
||||
entry->indexResolution = record->entry.indexResolution;
|
||||
entry->indexOffset = record->data_length;
|
||||
entry->payloadOffset = payload_position;
|
||||
entry->payloadOffset = payload_position >> ctx->user_data_ddt_header.blockAlignmentShift;
|
||||
|
||||
record->entry = *entry;
|
||||
|
||||
@@ -4668,7 +4671,7 @@ static int32_t write_flux_capture_payload(aaruformat_context *ctx, FluxCaptureRe
|
||||
* **Format Considerations:**
|
||||
* - The FluxDataBlock must be written after all DataStreamPayloadBlock entries
|
||||
* - The entry count in FluxHeader must match the number of payload blocks written
|
||||
* - Each FluxEntry's payloadOffset must point to a valid DataStreamPayloadBlock
|
||||
* - Each FluxEntry's payloadOffset must point to a valid DataStreamPayloadBlock (stored divided by block alignment)
|
||||
* - The CRC64 in FluxHeader enables verification of entry array integrity
|
||||
* - Multiple captures per track are supported via captureIndex differentiation
|
||||
*
|
||||
@@ -4798,6 +4801,7 @@ static int32_t write_flux_blocks(aaruformat_context *ctx)
|
||||
FluxHeader header = {0};
|
||||
header.identifier = FluxDataBlock;
|
||||
header.entries = (uint16_t)capture_count;
|
||||
header.blockAlignmentShift = ctx->user_data_ddt_header.blockAlignmentShift;
|
||||
header.crc64 =
|
||||
capture_count == 0 ? 0 : aaruf_crc64_data((const uint8_t *)entries, capture_count * sizeof(FluxEntry));
|
||||
|
||||
|
||||
@@ -1152,6 +1152,7 @@ struct FluxHeader
|
||||
{
|
||||
BlockType identifier;
|
||||
u16 entries;
|
||||
u8 blockAlignmentShift;
|
||||
u64 crc64;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user