Skip to content

Commit 5d395fb

Browse files
author
Grok Compression
committed
selective fetch: document and clean up
1 parent 2bbfda3 commit 5d395fb

2 files changed

Lines changed: 84 additions & 44 deletions

File tree

src/lib/core/codestream/decompress/CodeStreamDecompress.cpp

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,6 +1743,33 @@ bool CodeStreamDecompress::fetchByTile(
17431743
return true;
17441744
}
17451745

1746+
void CodeStreamDecompress::enqueueTileForDecompress(
1747+
uint16_t tileIndex, std::shared_ptr<TPFetchSeq> decompressSeq, uint16_t numTileCols,
1748+
Rect32 unreducedImageBounds,
1749+
std::function<std::function<void()>(ITileProcessor*)> postGenerator)
1750+
{
1751+
if(compressedChunkCache_)
1752+
compressedChunkCache_->put(tileIndex, decompressSeq);
1753+
1754+
int32_t tileRow = tileIndex / numTileCols;
1755+
int32_t prev = maxFetchedTileRow_.load(std::memory_order_acquire);
1756+
while(prev < tileRow &&
1757+
!maxFetchedTileRow_.compare_exchange_weak(prev, tileRow, std::memory_order_release,
1758+
std::memory_order_acquire))
1759+
{
1760+
}
1761+
decompressQueue_->push(
1762+
[this, tileIndex, decompressSeq, unreducedImageBounds, postGenerator]() {
1763+
const auto tileProcessor = getTileProcessor(tileIndex);
1764+
auto* tp = dynamic_cast<TileProcessor*>(tileProcessor);
1765+
if(tp)
1766+
tp->setSelectiveFetch(true);
1767+
auto decompressTask = genDecompressTileTLMTask(tileProcessor, decompressSeq,
1768+
unreducedImageBounds, postGenerator);
1769+
decompressTask();
1770+
});
1771+
}
1772+
17461773
bool CodeStreamDecompress::fetchByTileSelective(
17471774
std::set<uint16_t>& slated, Rect32 unreducedImageBounds,
17481775
std::function<std::function<void()>(ITileProcessor*)> postGenerator)
@@ -2039,7 +2066,17 @@ bool CodeStreamDecompress::fetchByTileSelective(
20392066
selectiveFetchTiles->insert(tileIndex);
20402067
}
20412068

2042-
// Reuse Phase 1 data for tiles where all needed data fits within the header fetch
2069+
// Phase 1 data reuse: avoid re-fetching data that was already downloaded during the
2070+
// header probe. For small tiles or low target resolutions, the 4 KB header fetch often
2071+
// contains all the packets needed for the reduced decompress. In that case we build the
2072+
// decompression sequence directly from the Phase 1 buffer and skip the Phase 2 HTTP request.
2073+
//
2074+
// Two layouts are handled:
2075+
// - Contiguous (selParts count == tile-part count): each entry maps 1:1 to a tile-part
2076+
// buffer; we copy the prefix of the Phase 1 buffer.
2077+
// - Disjoint (selParts count > tile-part count, single tile-part only): entries reference
2078+
// different sub-ranges of one Phase 1 buffer; we assemble them into a single contiguous
2079+
// buffer identical to the Phase 2 disjoint callback output.
20432080
struct PrefetchedTile
20442081
{
20452082
uint16_t tileIndex;
@@ -2175,29 +2212,8 @@ bool CodeStreamDecompress::fetchByTileSelective(
21752212

21762213
// Queue pre-fetched tiles directly for decompression (reusing Phase 1 data)
21772214
for(auto& pf : prefetchedTiles)
2178-
{
2179-
if(compressedChunkCache_)
2180-
compressedChunkCache_->put(pf.tileIndex, pf.decompressSeq);
2181-
2182-
int32_t tileRow = pf.tileIndex / numTileCols;
2183-
int32_t prev = maxFetchedTileRow_.load(std::memory_order_acquire);
2184-
while(prev < tileRow &&
2185-
!maxFetchedTileRow_.compare_exchange_weak(prev, tileRow, std::memory_order_release,
2186-
std::memory_order_acquire))
2187-
{
2188-
}
2189-
decompressQueue_->push(
2190-
[this, tileIndex = pf.tileIndex, decompressSeq = pf.decompressSeq,
2191-
unreducedImageBounds, postGenerator]() {
2192-
const auto tileProcessor = getTileProcessor(tileIndex);
2193-
auto* tp = dynamic_cast<TileProcessor*>(tileProcessor);
2194-
if(tp)
2195-
tp->setSelectiveFetch(true);
2196-
auto decompressTask = genDecompressTileTLMTask(tileProcessor, decompressSeq,
2197-
unreducedImageBounds, postGenerator);
2198-
decompressTask();
2199-
});
2200-
}
2215+
enqueueTileForDecompress(pf.tileIndex, pf.decompressSeq, numTileCols, unreducedImageBounds,
2216+
postGenerator);
22012217

22022218
if(!selectiveFetchTiles->empty())
22032219
{
@@ -2269,26 +2285,8 @@ bool CodeStreamDecompress::fetchByTileSelective(
22692285
decompressSeq = tilePartSeq;
22702286
}
22712287

2272-
if(compressedChunkCache_)
2273-
compressedChunkCache_->put(tileIndex, decompressSeq);
2274-
2275-
int32_t tileRow = tileIndex / numTileCols;
2276-
int32_t prev = maxFetchedTileRow_.load(std::memory_order_acquire);
2277-
while(prev < tileRow &&
2278-
!maxFetchedTileRow_.compare_exchange_weak(prev, tileRow, std::memory_order_release,
2279-
std::memory_order_acquire))
2280-
{
2281-
}
2282-
decompressQueue_->push(
2283-
[this, tileIndex, decompressSeq, unreducedImageBounds, postGenerator]() {
2284-
const auto tileProcessor = getTileProcessor(tileIndex);
2285-
auto* tp = dynamic_cast<TileProcessor*>(tileProcessor);
2286-
if(tp)
2287-
tp->setSelectiveFetch(true);
2288-
auto decompressTask = genDecompressTileTLMTask(tileProcessor, decompressSeq,
2289-
unreducedImageBounds, postGenerator);
2290-
decompressTask();
2291-
});
2288+
enqueueTileForDecompress(tileIndex, decompressSeq, numTileCols, unreducedImageBounds,
2289+
postGenerator);
22922290
}
22932291
}));
22942292
} // if(!selectiveFetchTiles->empty())

src/lib/core/codestream/decompress/CodeStreamDecompress.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,9 +466,51 @@ class CodeStreamDecompress final : public CodeStream, public IDecompressor
466466
bool fetchByTile(std::set<uint16_t>& slated, Rect32 unreducedImageBounds,
467467
std::function<std::function<void()>(ITileProcessor*)> postGenerator);
468468

469+
/**
470+
* @brief Two-phase PLT-based selective tile fetch for reduced resolution decompression.
471+
*
472+
* Phase 1 (header probe): Fetches a small prefix (4 KB) of each tile-part to extract
473+
* the PLT marker (packet lengths) and SOD offset without downloading full tile data.
474+
*
475+
* Range computation: Uses PLT packet lengths and the tile's progression order to compute
476+
* the minimal byte ranges needed for the target resolution level (reduce > 0).
477+
* For resolution-first progressions (RLCP, RPCL) this produces a single contiguous range;
478+
* for layer-first (LRCP, CPRL, PCRL) it may produce disjoint ranges.
479+
*
480+
* Phase 1 data reuse: When the computed ranges fit entirely within the 4 KB already
481+
* fetched in Phase 1, the data is reused directly — no Phase 2 HTTP request is issued.
482+
* This is common for small tiles or low-resolution decompressions where all needed
483+
* packets are contained in the initial header fetch.
484+
*
485+
* Phase 2 (selective fetch): For tiles whose needed data exceeds the Phase 1 buffer,
486+
* truncated or disjoint HTTP range requests are issued to fetch only the required
487+
* packet data.
488+
*
489+
* @param slated set of tile indices to decompress
490+
* @param unreducedImageBounds unreduced image bounds for decompress tasks
491+
* @param postGenerator factory for post-decompress callbacks
492+
* @return true if tiles were scheduled for decompression
493+
*/
469494
bool fetchByTileSelective(std::set<uint16_t>& slated, Rect32 unreducedImageBounds,
470495
std::function<std::function<void()>(ITileProcessor*)> postGenerator);
471496

497+
/**
498+
* @brief Enqueue a tile for decompression via the decompress pipeline.
499+
*
500+
* Updates the compressed chunk cache, advances the max-fetched tile row,
501+
* and pushes a decompress task onto the decompress queue.
502+
*
503+
* @param tileIndex tile index
504+
* @param decompressSeq tile-part fetch sequence with data and MemStreams
505+
* @param numTileCols number of tile columns in the grid
506+
* @param unreducedImageBounds unreduced image bounds for decompress tasks
507+
* @param postGenerator factory for post-decompress callbacks
508+
*/
509+
void enqueueTileForDecompress(
510+
uint16_t tileIndex, std::shared_ptr<TPFetchSeq> decompressSeq, uint16_t numTileCols,
511+
Rect32 unreducedImageBounds,
512+
std::function<std::function<void()>(ITileProcessor*)> postGenerator);
513+
472514
/**
473515
* @brief Scratch @ref GrkImage for decompressor
474516
* This image may composite multiple tiles, if needed.

0 commit comments

Comments
 (0)