Skip to content

Commit 759d7a7

Browse files
author
Grok Compression
committed
slated tiles: filter out already decompressed tiles for sequential
1 parent e27a13e commit 759d7a7

3 files changed

Lines changed: 46 additions & 50 deletions

File tree

.vscode/launch.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -848,18 +848,18 @@
848848
"type": "cppdbg",
849849
"request": "launch",
850850
"program": "${workspaceFolder}/build/bin/grk_decompress",
851+
// "program": "/usr/bin/valgrind",
851852
"args": [
853+
//"${workspaceFolder}/build/bin/grk_decompress",
852854
"-i",
853-
"$HOME/temp/clusterfuzz-testcase-minimized-grk_decompress_fuzzer-4737912531910656",
855+
"$HOME/temp/clusterfuzz-testcase-minimized-grk_decompress_fuzzer-6503262076338176",
854856
"-d 0,0,1024,1024",
855-
// "-t",
856-
// "20",
857857
"-o",
858858
"$HOME/temp/fuzz.pgx"
859859

860860
],
861861
"environment": [
862-
{ "name": "GRK_DEBUG", "value": "3" },
862+
{ "name": "GRK_DEBUG", "value": "4" },
863863
],
864864
"cwd": "${workspaceFolder}",
865865
"MIMode": "gdb",

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

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ bool CodeStreamDecompress::decompress(grk_plugin_tile* tile)
212212

213213
multiTileComposite_->postReadHeader(&cp_);
214214
tileCache_->init(cp_.t_grid_width_ * cp_.t_grid_height_);
215-
auto slated = tilesToDecompress_.getSlatedTiles();
216-
if(!decompressImpl(slated))
215+
auto slatedTiles = tilesToDecompress_.getSlatedTiles();
216+
if(!decompressImpl(slatedTiles))
217217
return false;
218218

219219
// If all slated tiles were already cached, decompressImpl returned
@@ -222,7 +222,7 @@ bool CodeStreamDecompress::decompress(grk_plugin_tile* tile)
222222
// complete so that grk_decompress_wait() won't hang.
223223
if(tileCompletion_)
224224
{
225-
for(auto tileIndex : slated)
225+
for(auto tileIndex : slatedTiles)
226226
{
227227
auto cacheEntry = tileCache_->get(tileIndex);
228228
if(!cacheEntry)
@@ -244,32 +244,32 @@ bool CodeStreamDecompress::decompress(grk_plugin_tile* tile)
244244
return success_;
245245
}
246246

247-
bool CodeStreamDecompress::decompressImpl(std::set<uint16_t> slated)
247+
bool CodeStreamDecompress::decompressImpl(std::set<uint16_t> pendingTiles)
248248
{
249-
// Filter out fully cached tiles from slated
250-
std::erase_if(slated, [this](uint16_t index) {
249+
// Filter out fully cached tiles
250+
std::erase_if(pendingTiles, [this](uint16_t index) {
251251
auto cacheEntry = tileCache_->get(index);
252252
if(!cacheEntry)
253253
return false;
254254
auto proc = cacheEntry->processor;
255255
return proc->isBestEffortDecompressed() || (proc->getImage() && !cacheEntry->dirty_);
256256
});
257-
if(slated.empty())
257+
if(pendingTiles.empty())
258258
return true;
259259

260260
// Extract LRU-evicted tiles that can be re-decompressed from cache
261261
// (opt-in: only when compressed chunk cache is active and TLM is present)
262262
std::set<uint16_t> reDecompressTiles;
263263
if(compressedChunkCache_ && cp_.hasTLM())
264264
{
265-
for(auto it = slated.begin(); it != slated.end();)
265+
for(auto it = pendingTiles.begin(); it != pendingTiles.end();)
266266
{
267267
auto cacheEntry = tileCache_->get(*it);
268268
if(cacheEntry && cacheEntry->processor->getImage() && !cacheEntry->processor->getTile() &&
269269
cacheEntry->dirty_ && compressedChunkCache_->contains(*it))
270270
{
271271
reDecompressTiles.insert(*it);
272-
it = slated.erase(it);
272+
it = pendingTiles.erase(it);
273273
}
274274
else
275275
{
@@ -280,8 +280,8 @@ bool CodeStreamDecompress::decompressImpl(std::set<uint16_t> slated)
280280

281281
// Require tile_ to exist for differential updates — an LRU-evicted tile
282282
// without cached compressed data must go through the full decompress path
283-
bool doDifferential = !slated.empty();
284-
for(auto& tileIndex : slated)
283+
bool doDifferential = !pendingTiles.empty();
284+
for(auto& tileIndex : pendingTiles)
285285
{
286286
auto cacheEntry = tileCache_->get(tileIndex);
287287
if(!cacheEntry || !cacheEntry->processor->getImage() || !cacheEntry->processor->getTile())
@@ -313,13 +313,13 @@ bool CodeStreamDecompress::decompressImpl(std::set<uint16_t> slated)
313313
cacheEntry->dirty_ = false;
314314
}
315315

316-
if(slated.empty())
316+
if(pendingTiles.empty())
317317
return true;
318318

319319
// synchronous batch init
320320
if(doTileBatching() && !cp_.hasTLM())
321321
{
322-
batchTileUnscheduledSequential_ = (uint16_t)slated.size();
322+
batchTileUnscheduledSequential_ = (uint16_t)pendingTiles.size();
323323
batchTileScheduleHeadroomSequential_ =
324324
batchTileHeadroomIncrement(batchTileInitialRows_, batchTileUnscheduledSequential_);
325325
batchTileScheduledRows_ = batchTileInitialRows_;
@@ -337,14 +337,14 @@ bool CodeStreamDecompress::decompressImpl(std::set<uint16_t> slated)
337337
return postMultiTile(tp); // Return the result directly
338338
};
339339

340-
if(fetchByTile(slated, scratchImage_->getBounds(), generator))
340+
if(fetchByTile(pendingTiles, scratchImage_->getBounds(), generator))
341341
return true;
342342

343343
// b) prepare for TLM decompress
344344
tilePartFetchFlat_ = std::make_shared<TPFetchSeq>();
345345
tilePartFetchByTile_ =
346346
std::make_shared<std::unordered_map<uint16_t, std::shared_ptr<TPFetchSeq>>>();
347-
TPFetchSeq::genCollections(&cp_.tlmMarkers_->getTileParts(), slated, tilePartFetchFlat_,
347+
TPFetchSeq::genCollections(&cp_.tlmMarkers_->getTileParts(), pendingTiles, tilePartFetchFlat_,
348348
tilePartFetchByTile_);
349349
}
350350
else
@@ -369,7 +369,7 @@ bool CodeStreamDecompress::decompressImpl(std::set<uint16_t> slated)
369369
// 1. differential decompression
370370
if(doDifferential)
371371
{
372-
for(auto& tileIndex : slated)
372+
for(auto& tileIndex : pendingTiles)
373373
{
374374
if(doDifferential)
375375
{
@@ -389,9 +389,9 @@ bool CodeStreamDecompress::decompressImpl(std::set<uint16_t> slated)
389389

390390
std::function<void()> task;
391391
if(cp_.hasTLM())
392-
task = [this, slated]() { decompressTLM(slated); };
392+
task = [this, pendingTiles]() { decompressTLM(pendingTiles); };
393393
else
394-
task = [this]() { decompressSequential(); };
394+
task = [this, pendingTiles]() { decompressSequential(pendingTiles); };
395395

396396
decompressWorker_ = std::thread(task);
397397
return true;
@@ -423,26 +423,26 @@ bool CodeStreamDecompress::schedule(ITileProcessor* tileProcessor, bool multiTil
423423

424424
// TLM ///////////////////////////////////////////////////////////////
425425

426-
void CodeStreamDecompress::decompressTLM(const std::set<uint16_t>& slated)
426+
void CodeStreamDecompress::decompressTLM(const std::set<uint16_t>& pendingTiles)
427427
{
428-
// 1 schedule all slated tiles
428+
// 1 schedule all pending tiles
429429
if(!doTileBatching())
430430
{
431-
for(const auto& tileIndex : slated)
431+
for(const auto& tileIndex : pendingTiles)
432432
{
433433
if(!schedule(getTileProcessor(tileIndex), true))
434434
break;
435435
}
436436
return;
437437
}
438438

439-
// 2. push all slated tiles into the queue
440-
for(const auto& value : slated)
439+
// 2. push all pending tiles into the queue
440+
for(const auto& value : pendingTiles)
441441
batchTileQueueTLM_.push(value);
442442

443443
// 3. schedule first N rows
444444
uint16_t initialBatchCount =
445-
batchTileHeadroomIncrement(batchTileInitialRows_, (uint16_t)slated.size());
445+
batchTileHeadroomIncrement(batchTileInitialRows_, (uint16_t)pendingTiles.size());
446446
batchTileScheduledRows_ = batchTileInitialRows_;
447447
{
448448
std::lock_guard<std::mutex> lock(batchTileQueueMutex_);
@@ -501,7 +501,7 @@ void CodeStreamDecompress::decompressSequentialPrepare(void)
501501
stream_->memAdvise(stream_->tell(), 0, GrkAccessPattern::ACCESS_RANDOM);
502502
}
503503

504-
void CodeStreamDecompress::decompressSequential(void)
504+
void CodeStreamDecompress::decompressSequential(const std::set<uint16_t>& pendingTiles)
505505
{
506506
bool foundUnknownMarker = false;
507507
while(!markerParser_.endOfCodeStream() && !foundUnknownMarker)
@@ -511,10 +511,10 @@ void CodeStreamDecompress::decompressSequential(void)
511511
{
512512
if(!sequentialParseAndSchedule(true))
513513
{
514-
// If we've exhausted all slated tiles' markers or the codestream
514+
// If we've exhausted all pending tiles' markers or the codestream
515515
// ran out of data (truncated image), stop gracefully.
516-
if(tileCache_->allSlatedSOTMarkersParsed(tilesToDecompress_.getSlatedTiles()) ||
517-
markerParser_.endOfCodeStream() || stream_->numBytesLeft() == 0)
516+
if(tileCache_->allSlatedSOTMarkersParsed(pendingTiles) || markerParser_.endOfCodeStream() ||
517+
stream_->numBytesLeft() == 0)
518518
break;
519519
success_ = false;
520520
break;
@@ -548,33 +548,29 @@ void CodeStreamDecompress::decompressSequential(void)
548548

549549
// check for corrupt Adobe files where 5 tile parts per tile are signalled
550550
// but there are actually 6.
551-
if(markerParser_.currId() == SOT &&
552-
tileCache_->allSlatedSOTMarkersParsed(tilesToDecompress_.getSlatedTiles()) &&
551+
if(markerParser_.currId() == SOT && tileCache_->allSlatedSOTMarkersParsed(pendingTiles) &&
553552
markerParser_.checkForIllegalTilePart())
554553
{
555554
success_ = false;
556555
break;
557556
}
558557

559-
if(tileCache_->allSlatedSOTMarkersParsed(tilesToDecompress_.getSlatedTiles()))
558+
if(tileCache_->allSlatedSOTMarkersParsed(pendingTiles))
560559
break;
561560
}
562561

563562
// Best-effort: schedule incomplete tiles (those with some tile parts parsed
564563
// but not all) for decompression with whatever data they have.
565-
if(!cp_.hasTLM())
564+
for(auto tileIndex : pendingTiles)
566565
{
567-
for(auto tileIndex : tilesToDecompress_.getSlatedTiles())
566+
auto cached = tileCache_->get(tileIndex);
567+
if(cached && cached->processor && !cached->processor->scheduledForDecompression() &&
568+
cached->processor->hasUnparsedTileParts())
568569
{
569-
auto cached = tileCache_->get(tileIndex);
570-
if(cached && cached->processor && !cached->processor->scheduledForDecompression() &&
571-
cached->processor->hasUnparsedTileParts())
572-
{
573-
cached->processor->setTruncated();
574-
cached->processor->prepareForDecompression();
575-
if(!cached->processor->hasError())
576-
schedule(cached->processor, true);
577-
}
570+
cached->processor->setTruncated();
571+
cached->processor->prepareForDecompression();
572+
if(!cached->processor->hasError())
573+
schedule(cached->processor, true);
578574
}
579575
}
580576

@@ -583,7 +579,7 @@ void CodeStreamDecompress::decompressSequential(void)
583579
// being decompressed asynchronously and must not be completed here.
584580
if(tileCompletion_)
585581
{
586-
for(auto tileIndex : tilesToDecompress_.getSlatedTiles())
582+
for(auto tileIndex : pendingTiles)
587583
{
588584
auto cached = tileCache_->get(tileIndex);
589585
if(!cached || !cached->processor || cached->processor->hasUnparsedTileParts())

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class CodeStreamDecompress final : public CodeStream, public IDecompressor
138138
*
139139
* @return true if successful
140140
*/
141-
bool decompressImpl(std::set<uint16_t> slated);
141+
bool decompressImpl(std::set<uint16_t> pendingTiles);
142142

143143
bool decompressTileImpl(uint16_t tile_index);
144144

@@ -318,8 +318,8 @@ class CodeStreamDecompress final : public CodeStream, public IDecompressor
318318
Rect32 unreducedImageBounds,
319319
std::function<std::function<void()>(ITileProcessor*)> postGenerator);
320320

321-
void decompressSequential(void);
322-
void decompressTLM(const std::set<uint16_t>& slated);
321+
void decompressSequential(const std::set<uint16_t>& pendingTiles);
322+
void decompressTLM(const std::set<uint16_t>& pendingTiles);
323323

324324
bool doTileBatching(void);
325325

0 commit comments

Comments
 (0)