KDU Implementation

This page documents the code implementing calls to the Kakadu library used to read and write JPEG2000 files in Linden Lab's official Viewers (development versions and all released viewers).
Note to TPV developers: If you want to use that code, you need to get a license from Kakadu, build the library and link it to the Viewer. This documentation gives some guidelines on how to do that.
== Objective ==
In Snowstorm sprint 8, we took on the task to update the old v4.2.1 Kakadu library to the newer v6.4.1 version. In doing so, we tried to address the following issues:
* Performance: take advantage of the improvements provided by a newer version of the library
* Performance: study Kakadu v6.4.1 and see if some new techniques could be used to improve the texture decompression performance
* Linking: move from a dynamic linking scheme to a static linking scheme so that we conform to the terms of the Kakadu license
* Open Sourcing: get rid of the old proprietary llkdu libraries and instead make the llkdu code open source so that 3rd party who do have a proper Kakadu license can produce a viewer using that library
Improving decompression performance helps alleviate common "lag" problems: gray prims on loading or teleport, blurry textures, weird looking abstract sculpties, and so on. Decompression alone though is not the source of all lag issues.
Also, the JPEG2000 architecture gives us methods to load only the sub region of the relevant resolution needed by the viewer to render a piece of texture. Currently though, the viewer loads much more than it needs for general textures and not enough for sculpties. The viewer is not using all the Pyramidal Parametrics magic it could (it does once the texture is loaded as an OpenGL texture but not at fetch time).
== Implementation ==
=== KDU Libraries ===
Linden Lab produces KDU binaries (mentioned in install.xml) that are only accessible to Linden Lab for licensing reasons.
TPV developers who wish to make use of this library for JPEG2000 need to get a license from Kakadu and build their own library.
Currently, the viewer uses only the Kakadu coresys library. TPV developers need to build a static version of this library, rename it as appropriate and drop it in the /libraries folder structure along with other 3rd party libraries. Kakadu headers need to be dropped in a libraries/include/kdu folder. Please refer to indra/cmake/LLKDU.cmake for naming conventions and detailed folder structure.
Linden Lab is using 32-bit binaries. It is possible to build the Kakadu libraries for 64 bits. However, Linden Lab does not test or support 64-bit binaries; no tests have been performed using such binaries and linking with a 64 bit viewer.
Reference:
* Kakadu
=== Building with KDU ===
Once the libraries and headers are installed, the developer just needs to specify -DUSE_KDU:BOOL=ON when invoking cmake or using develop.py which will pass the parameter to cmake, in order to link with KDU.
From a build standpoint, here's a detailed list of what has been changed in order to build with this new library and statically link to it:
* indra/cmake/Copy3rdPartyLibs.cmake, CopyWinLibs.cmake: Suppressed everything that was llkdu.dll copy orders.
* indra/cmake/LLKDU.cmake: New file. Sets where libraries and include for KDU are to be found.
* indra/llimage/CMakeLists.txt: Suppressed the explicitely link to LLImageJ2COJ library.
* indra/newview/CMakeLists.txt: Added the static kdu in the target_link_libraries, suppress the dependency on dll, add code to switch to openjpeg linking if kdu absent.
* indra/integration_tests/llui_libtest/CMakeLists.txt: Added explicit link to LLImageJ2COJ and LLIMAGE so that it gets build without relying on newview or LLIMAGE linking to LLImageJ2COJ.
* llimage/llimagej2c: Eliminated the llkdu.dll loading and the switch between openjpeg and kdu implementations through Impl. The switch is done at build time now using USE_KDU.
* indra/llkdu: New folder and files. Implementation of the KDU calls.
Reference:
* STORM-151
=== indra/llkdu ===
The KDU implementation is available in indra/llkdu and properly open sourced.
It contains only 2 modules (llimagej2ckdu and llkdumem) and one set of unit tests (tests/llimagej2ckdu_test.cpp).
llkdumem contains only memory helpers classes adapted to Kakadu code to handle data buffers in and out the compression/decompression library.
llimagej2ckdu contains the LLImageJ2CKDU class, inheriting from the viewer LLImageJ2CImpl and implementing the 3 virtual methods essential for JPEG2000 compression/decompression:
* getMetadata()
* decodeImpl()
* encodeImpl()
Documentation:
* STORM-146
=== Performance Data ===
As part of this work, we created a new set of performance metrics in order to compare the performances of v4.2.1 to v.6.4.1. The whole performance metric framework has been deeply reworked and improved as a result, allowing for specific test metrics to be produced and independently saved and analyzed.
The KDU results show that this new version is 30% faster on Mac and Linux, 12% faster on Windows in decompression than the old one.
References:
* STORM-105
* Performance Testers
=== KDU_X86_INTRINSICS ===
The Kakadu documentation mentions that performance on 32bits architecture are better using the KDU_X86_INTRINSICS compilation directive. We ran some tests using that directive on Mac and Windows and found that the performance of v6.4.1 were actually back to the level of v4.2.1 for Mac, even slightly worse for Windows (see tables here under).
We therefore do not recommend to use this compilation directive.
Mac : Base = Kakadu v4.2.1 vs. Target = Kakadu v6.4.1 with KDU_X86_INTRINSICS	
<tab class=lltable head=top border=1>
Metric	 Base(B)	 Target(T)	 Diff(T-B)	 Percentage(100*T/B)
Time Decompression (s)	 55.2314	 49.0371	 -6.1943	 88.7848
Volume In Decompression (kB)	 59110.2734	 56797.7852	 -2312.4883	 96.0878
Volume Out Decompression (kB)	 571937.6875	 532159.9375	 -39777.7500	 93.0451
Decompression Ratio (x:1)	 9.6758	 9.3694	 -0.3064	 96.8334
Perf Decompression (kB/s)	 1070.2286	 1158.2612	 88.0326	 108.2256
Time Compression (s)	 0.3415	 0.4206	 0.0791	 123.1523
Volume In Compression (kB)	 2359.2959	 3145.7280	 786.4321	 133.3333
Volume Out Compression (kB)	 294.5330	 392.3960	 97.8630	 133.2265
Compression Ratio (x:1)	 8.0103	 8.0167	 0.0064	 100.0802
Perf Compression (kB/s)	 6908.8086	 7479.9619	 571.1533	 108.2670
</tab>
Windows : Base = Kakadu v4.2.1 vs. Target = Kakadu v6.4.1 with KDU_X86_INTRINSICS	
<tab class=lltable head=top border=1>
Metric	 Base(B)	 Target(T)	 Diff(T-B)	 Percentage(100*T/B)
Time Decompression (s)	 32.7087	 35.8386	 3.1299	 109.5690
Volume In Decompression (kB)	 69416.0313	 70317.5547	 901.5234	 101.2987
Volume Out Decompression (kB)	 639489.0625	 659563.9375	 20074.8750	 103.1392
Decompression Ratio (x:1)	 9.2124	 9.3798	 0.1674	 101.8169
Perf Decompression (kB/s)	 2122.2468	 1962.0601	 -160.1868	 92.4520
Time Compression (s)	 0.3180	 0.3279	 0.0099	 103.1266
Volume In Compression (kB)	 3145.7280	 3145.7280	 0.0000	 100.0000
Volume Out Compression (kB)	 393.0400	 392.8940	 -0.1460	 99.9629
Compression Ratio (x:1)	 8.0036	 8.0066	 0.0030	 100.0372
Perf Compression (kB/s)	 9892.3506	 9592.4316	 -299.9189	 96.9682
</tab>
References:
* STORM-748
* Performance Testers
== References ==
* JPEG2000: Wikipedia article. Read this short and clear review first.
* jpeg.org: The portal of the official JPEG organization. Not much substance unfortunately.
* Taubman: All papers by Taubman, the main author of Kakadu. Excellent source of ideas, pretty academic though.
* JPEG 2000 Image Coding Standard: Independent paper with very clear definition of more arcane JPEG2000 notions.
* OpenJpeg: The official page of the OpenJpeg project.