Repository navigation
svac3: loop filters in a wavefront behind the reconstruction - #12
Conversation
Deblocking and SAO now follow the reconstruction LCU row by LCU row instead of waiting for the whole picture. Band k is deblocked once row k + 1 is reconstructed (its bottom samples are the next row's intra references), its vertical edges and then its horizontal ones; SAO of LCU row k runs once band k is, from a copy of the deblocked rows it reads made just before they are first changed. Band after band gives what filtering the whole picture at once gives: a band's horizontal edges read only rows whose vertical edges are done and no later edge writes. With 3 threads or more the filters run on a thread of their own, a third stage after parsing and reconstruction. With 1 they run on the decoding thread as rows complete; with 2, and for pictures whose patches are narrower than the picture (rows not completing in order), the whole picture is filtered at the end on the pool, as before. svac3_deblock_rows() and svac3_sao_rows() filter a range of rows; the row-end record (REC_ROW) carries the reconstruction's progress.
PR Summary by QodoPipeline SVAC3 loop filters behind row reconstruction
AI Description
Diagram
High-Level Assessment
Files changed (3)
|
Code Review by Qodo
1.
|
plane_edges() took the range's first row as an edge position: with row ranges that are not multiples of 8 in chroma (LCUs of 8 rows), it filtered between the real edges. Horizontal edges now start at the first multiple of 8 in the range, so each belongs to exactly one range. The wavefront also needs LCUs of 16 rows or more, which is all the corpus has; smaller ones filter the whole picture at the end. test_lf deblocks random pictures in consecutive ranges of 8, 16, 24, 32 and 64 rows against deblocking them whole; without the fix 809 of 2000 differ.
|
Thanks, valid; fixed in the latest commit, in two ways.
New
ctest: 35/35. |
The first of two follow-ups to #11, both informed by how the vendor decoder works (its symbol table:
ThreadParseLcuRow,ProcessLcuRow,db_filter_ctu,SynchList…). Here the loop filters follow the reconstruction row by row instead of waiting for the whole picture. The next PR will decode several pictures at once, using the per-row progress this one establishes.What runs when (
filter_upto()):Why the output is identical: filtering band after band gives exactly what the whole picture at once gives. A band's horizontal edges read 4 rows above it. Those rows' vertical edges are already done, and no horizontal edge of the band above writes them (the edge 8 rows up writes at most 6 above). The corpus confirms it, as do every thread count and both patch layouts.
Scheduling
REC_ROW)Pictures whose patches are narrower than the picture, whose rows don't complete in order, are filtered at the end. Ready bands are filtered in one call.
Checks
test_api.Speed: idle Core Ultra 5 245K, P-cores, best of 3,
master(with #11) against this branch:At 3 and 4 threads libsvac3d is now ahead of the vendor decoder at 4 threads on every stream. Beyond 3 threads the three stages are each one thread; decoding several pictures at once is the next PR.