├── test ├── __init__.py └── data │ ├── 192x128_kodim15.png │ ├── kodim15_192x128_01p_yuv420_10b.yuv │ ├── kodim15_192x128_01p_yuv420_8b.yuv │ ├── kodim15_192x128_01p_yuv444_10b.yuv │ ├── kodim15_192x128_01p_yuv444_8b.yuv │ ├── D-BQSquare_224x128_60p_yuv420_8b.yuv │ ├── D-BQSquare-3frames_224x128_60p_yuv420_8b.yuv │ └── D-BQSquare-5frames_224x128_60p_yuv420_8b.yuv ├── coolchic ├── enc │ ├── component │ │ ├── intercoding │ │ │ └── __init__.py │ │ └── types.py │ ├── utils │ │ ├── device.py │ │ ├── misc.py │ │ └── manager.py │ ├── io │ │ ├── types.py │ │ ├── format │ │ │ ├── data_type.py │ │ │ └── png.py │ │ ├── framedata.py │ │ └── io.py │ ├── training │ │ └── metrics │ │ │ └── mse.py │ ├── bitstream │ │ └── utils.py │ └── nnquant │ │ ├── quantstep.py │ │ └── expgolomb.py ├── cpp │ ├── ups_cpu.cpp │ ├── common_randomness.h │ ├── warp.h │ ├── warp_cpu.h │ ├── warp_avx2.h │ ├── ups_cpu.h │ ├── ups_avx2.cpp │ ├── synblend_avx2.hpp │ ├── arm_cpu.h │ ├── syn_cpu.cpp │ ├── ccdecapi_cpu.cpp │ ├── ccdecapi_avx2.cpp │ ├── common_randomness.cpp │ ├── arm_avx2.cpp │ ├── ups_avx2.h │ ├── common_avx2.h │ ├── warp_common.h │ ├── common.h │ ├── cc-contexts.h │ ├── syn_cpu.h │ ├── arm_avx2.h │ ├── Contexts.cpp │ ├── CMakeLists.txt │ ├── TEncBinCoder.h │ ├── TDecBinCoder.h │ ├── frame-memory.h │ ├── TEncBinCoderCABAC.h │ ├── warp_common.cpp │ ├── cc-bitstream.h │ └── arm_cpu.cpp ├── dec │ └── nn.py └── decode.py ├── cfg ├── enc │ ├── debug.cfg │ ├── intra │ │ ├── fast_10k.cfg │ │ ├── medium_30k.cfg │ │ ├── perceptive.cfg │ │ └── slow_100k.cfg │ ├── inter │ │ └── tunable.cfg │ └── measure_enc_speed.cfg └── dec │ ├── intra │ ├── vlop.cfg │ ├── hop.cfg │ ├── lop.cfg │ └── mop.cfg │ ├── residue │ ├── vlop.cfg │ ├── hop.cfg │ ├── mop.cfg │ └── lop.cfg │ └── motion │ ├── lop.cfg │ └── mop.cfg ├── docs ├── source │ ├── _static │ │ ├── favicon.png │ │ ├── favicon_16x16.png │ │ ├── coolchic-logo-dark.png │ │ └── coolchic-logo-light.png │ ├── assets │ │ ├── kodak │ │ │ ├── rd.png │ │ │ ├── concat_img.png │ │ │ ├── all_complexity.png │ │ │ ├── all_complexity_dec.png │ │ │ ├── perf_decoding_time.png │ │ │ ├── perf_complexity_dec.png │ │ │ └── perf_complexity_enc.png │ │ ├── overview.pdf │ │ ├── overview.png │ │ ├── arm_context.png │ │ ├── logo_concat.png │ │ ├── logo_orange.png │ │ ├── jvet │ │ │ ├── rd_classB.png │ │ │ ├── rd_classC.png │ │ │ ├── rd_classD.png │ │ │ ├── rd_classE.png │ │ │ ├── rd_classF.png │ │ │ ├── rd_classBCDEF.png │ │ │ ├── concat_img_classB.png │ │ │ ├── concat_img_classC.png │ │ │ ├── concat_img_classD.png │ │ │ ├── concat_img_classE.png │ │ │ ├── concat_img_classF.png │ │ │ ├── all_complexity_classB.png │ │ │ ├── all_complexity_classC.png │ │ │ ├── all_complexity_classD.png │ │ │ ├── all_complexity_classE.png │ │ │ ├── all_complexity_classF.png │ │ │ ├── concat_img_classBCDEF.png │ │ │ ├── all_complexity_classBCDEF.png │ │ │ ├── all_complexity_dec_classB.png │ │ │ ├── all_complexity_dec_classC.png │ │ │ ├── all_complexity_dec_classD.png │ │ │ ├── all_complexity_dec_classE.png │ │ │ ├── all_complexity_dec_classF.png │ │ │ ├── perf_complexity_dec_classB.png │ │ │ ├── perf_complexity_dec_classC.png │ │ │ ├── perf_complexity_dec_classD.png │ │ │ ├── perf_complexity_dec_classE.png │ │ │ ├── perf_complexity_dec_classF.png │ │ │ ├── perf_complexity_enc_classB.png │ │ │ ├── perf_complexity_enc_classC.png │ │ │ ├── perf_complexity_enc_classD.png │ │ │ ├── perf_complexity_enc_classE.png │ │ │ ├── perf_complexity_enc_classF.png │ │ │ ├── perf_decoding_time_classB.png │ │ │ ├── perf_decoding_time_classC.png │ │ │ ├── perf_decoding_time_classD.png │ │ │ ├── perf_decoding_time_classE.png │ │ │ ├── perf_decoding_time_classF.png │ │ │ ├── all_complexity_dec_classBCDEF.png │ │ │ ├── perf_decoding_time_classBCDEF.png │ │ │ ├── perf_complexity_dec_classBCDEF.png │ │ │ └── perf_complexity_enc_classBCDEF.png │ │ ├── clic20-pro-valid │ │ │ ├── rd.png │ │ │ ├── concat_img.png │ │ │ ├── all_complexity.png │ │ │ ├── all_complexity_dec.png │ │ │ ├── perf_complexity_dec.png │ │ │ ├── perf_complexity_enc.png │ │ │ └── perf_decoding_time.png │ │ ├── coolchic-logo-dark.pdf │ │ ├── coolchic-logo-dark.png │ │ ├── coolchic-logo-light.pdf │ │ ├── coolchic-logo-light.png │ │ ├── encoding-time │ │ │ ├── encoding-time-clic.png │ │ │ ├── encoding-time-jvet-b.png │ │ │ ├── encoding-time-jvet-e.png │ │ │ └── encoding-time-kodak.png │ │ ├── video-ra-jvet-c │ │ │ ├── rd-C-BQMall_832x480_60p_yuv420_8b.png │ │ │ ├── rd-C-PartyScene_832x480_50p_yuv420_8b.png │ │ │ ├── rd-C-RaceHorses_832x480_30p_yuv420_8b.png │ │ │ └── rd-C-BasketballDrill_832x480_50p_yuv420_8b.png │ │ └── concat_img.sh │ ├── code_documentation │ │ ├── decoder │ │ │ └── index.rst │ │ ├── encoder │ │ │ ├── io │ │ │ │ ├── io.rst │ │ │ │ ├── format │ │ │ │ │ ├── png.rst │ │ │ │ │ ├── ppm.rst │ │ │ │ │ ├── yuv.rst │ │ │ │ │ └── index.rst │ │ │ │ └── index.rst │ │ │ ├── training │ │ │ │ ├── train.rst │ │ │ │ ├── warmup.rst │ │ │ │ ├── quantizemodel.rst │ │ │ │ ├── test.rst │ │ │ │ ├── loss.rst │ │ │ │ ├── preset.rst │ │ │ │ └── index.rst │ │ │ ├── nnquant │ │ │ │ ├── quantizemodel.rst │ │ │ │ ├── expgolomb.rst │ │ │ │ └── index.rst │ │ │ ├── component │ │ │ │ ├── intercoding │ │ │ │ │ ├── raft.rst │ │ │ │ │ ├── globalmotion.rst │ │ │ │ │ ├── index.rst │ │ │ │ │ └── warp.rst │ │ │ │ ├── video.rst │ │ │ │ ├── core │ │ │ │ │ ├── synthesis.rst │ │ │ │ │ ├── arm.rst │ │ │ │ │ ├── quantizer.rst │ │ │ │ │ ├── upsampling.rst │ │ │ │ │ └── index.rst │ │ │ │ ├── frame.rst │ │ │ │ ├── coolchic.rst │ │ │ │ └── index.rst │ │ │ ├── utils │ │ │ │ ├── index.rst │ │ │ │ └── codingstructure.rst │ │ │ └── index.rst │ │ └── overview.rst │ ├── video_compression │ │ ├── encoding.rst │ │ └── architecture.rst │ ├── results │ │ ├── video │ │ │ └── index.rst │ │ ├── image │ │ │ ├── index.rst │ │ │ ├── reproduce_results.rst │ │ │ ├── decoding_complexity.rst │ │ │ └── encoding_complexity.rst │ │ └── index.rst │ ├── _templates │ │ └── partials │ │ │ └── webfonts.html │ ├── image_compression │ │ ├── decoding_images.rst │ │ ├── overview.rst │ │ └── preset.rst │ ├── decoding │ │ └── decoding_images.rst │ ├── getting_started │ │ ├── new_stuff.rst │ │ ├── quickstart.rst │ │ ├── example.rst │ │ └── literature.rst │ ├── encoding │ │ ├── overview.rst │ │ ├── preset.rst │ │ └── video.rst │ └── index.rst ├── Makefile └── make.bat ├── samples └── bitstreams │ ├── a365_mse.cool │ ├── a365_wd.cool │ ├── kodim14.cool │ ├── martyn-seddon-220.cool │ ├── B-Cactus_1920x1080_50p_yuv420_8b.cool │ └── C-BasketballDrill_832x480_50p_yuv420_8b.cool ├── CONTRIBUTORS.md ├── pyproject.toml ├── .gitignore ├── .github └── workflows │ ├── sanity-check.yml │ └── static-pages.yml ├── toolbox └── toolbox │ ├── common │ ├── cliprint.py │ └── io │ │ ├── png.py │ │ └── image.py │ ├── yuv_concat.py │ ├── identify.py │ └── yuv_extract.py ├── LICENSE.txt ├── LICENSE_CABAC.txt └── results ├── v4.0 └── video-ra-jvet-c.tsv ├── v4.1 └── video-ra-jvet-c.tsv ├── v4.2 └── video-ra-jvet-c.tsv └── v1.0 └── image-kodak.tsv /test/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /coolchic/enc/component/intercoding/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cfg/enc/debug.cfg: -------------------------------------------------------------------------------- 1 | start_lr = 1e-2 2 | n_train_loops = 1 3 | preset = debug 4 | -------------------------------------------------------------------------------- /cfg/enc/intra/fast_10k.cfg: -------------------------------------------------------------------------------- 1 | n_itr = 10000 2 | start_lr = 1e-2 3 | n_train_loops = 1 4 | preset = c3x_intra 5 | -------------------------------------------------------------------------------- /cfg/enc/intra/medium_30k.cfg: -------------------------------------------------------------------------------- 1 | n_itr = 30000 2 | start_lr = 1e-2 3 | n_train_loops = 1 4 | preset = c3x_intra 5 | -------------------------------------------------------------------------------- /cfg/enc/intra/perceptive.cfg: -------------------------------------------------------------------------------- 1 | n_itr = 10000 2 | start_lr = 1e-2 3 | n_train_loops = 1 4 | tune = wasserstein 5 | -------------------------------------------------------------------------------- /cfg/enc/intra/slow_100k.cfg: -------------------------------------------------------------------------------- 1 | n_itr = 100000 2 | start_lr = 1e-2 3 | n_train_loops = 1 4 | preset = c3x_intra 5 | -------------------------------------------------------------------------------- /coolchic/enc/utils/device.py: -------------------------------------------------------------------------------- 1 | from typing import Literal 2 | 3 | POSSIBLE_DEVICE = Literal["cpu", "cuda:0"] 4 | -------------------------------------------------------------------------------- /cfg/enc/inter/tunable.cfg: -------------------------------------------------------------------------------- 1 | start_lr = 5e-3 2 | n_train_loops = 1 3 | preset = c3x_inter 4 | n_itr_pretrain_motion = 1000 -------------------------------------------------------------------------------- /cfg/enc/measure_enc_speed.cfg: -------------------------------------------------------------------------------- 1 | start_lr = 1e-2 2 | n_train_loops = 1 3 | n_itr = 1500 4 | preset = measure_speed 5 | -------------------------------------------------------------------------------- /test/data/192x128_kodim15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/test/data/192x128_kodim15.png -------------------------------------------------------------------------------- /docs/source/_static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/_static/favicon.png -------------------------------------------------------------------------------- /docs/source/assets/kodak/rd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/kodak/rd.png -------------------------------------------------------------------------------- /docs/source/assets/overview.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/overview.pdf -------------------------------------------------------------------------------- /docs/source/assets/overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/overview.png -------------------------------------------------------------------------------- /samples/bitstreams/a365_mse.cool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/samples/bitstreams/a365_mse.cool -------------------------------------------------------------------------------- /samples/bitstreams/a365_wd.cool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/samples/bitstreams/a365_wd.cool -------------------------------------------------------------------------------- /samples/bitstreams/kodim14.cool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/samples/bitstreams/kodim14.cool -------------------------------------------------------------------------------- /docs/source/assets/arm_context.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/arm_context.png -------------------------------------------------------------------------------- /docs/source/assets/logo_concat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/logo_concat.png -------------------------------------------------------------------------------- /docs/source/assets/logo_orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/logo_orange.png -------------------------------------------------------------------------------- /docs/source/_static/favicon_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/_static/favicon_16x16.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/rd_classB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/rd_classB.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/rd_classC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/rd_classC.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/rd_classD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/rd_classD.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/rd_classE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/rd_classE.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/rd_classF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/rd_classF.png -------------------------------------------------------------------------------- /docs/source/code_documentation/decoder/index.rst: -------------------------------------------------------------------------------- 1 | Decoder 2 | ======= 3 | 4 | .. toctree:: 5 | :hidden: 6 | 7 | This is our decoder doc -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | Authors: 2 | 3 | * Theo Ladune: theo.ladune@orange.com 4 | 5 | * Pierrick Philippe: pierrick.philippe@orange.com 6 | 7 | -------------------------------------------------------------------------------- /docs/source/assets/kodak/concat_img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/kodak/concat_img.png -------------------------------------------------------------------------------- /docs/source/_static/coolchic-logo-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/_static/coolchic-logo-dark.png -------------------------------------------------------------------------------- /docs/source/assets/clic20-pro-valid/rd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/clic20-pro-valid/rd.png -------------------------------------------------------------------------------- /docs/source/assets/coolchic-logo-dark.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/coolchic-logo-dark.pdf -------------------------------------------------------------------------------- /docs/source/assets/coolchic-logo-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/coolchic-logo-dark.png -------------------------------------------------------------------------------- /docs/source/assets/coolchic-logo-light.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/coolchic-logo-light.pdf -------------------------------------------------------------------------------- /docs/source/assets/coolchic-logo-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/coolchic-logo-light.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/rd_classBCDEF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/rd_classBCDEF.png -------------------------------------------------------------------------------- /samples/bitstreams/martyn-seddon-220.cool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/samples/bitstreams/martyn-seddon-220.cool -------------------------------------------------------------------------------- /docs/source/_static/coolchic-logo-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/_static/coolchic-logo-light.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/concat_img_classB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/concat_img_classB.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/concat_img_classC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/concat_img_classC.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/concat_img_classD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/concat_img_classD.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/concat_img_classE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/concat_img_classE.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/concat_img_classF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/concat_img_classF.png -------------------------------------------------------------------------------- /docs/source/assets/kodak/all_complexity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/kodak/all_complexity.png -------------------------------------------------------------------------------- /test/data/kodim15_192x128_01p_yuv420_10b.yuv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/test/data/kodim15_192x128_01p_yuv420_10b.yuv -------------------------------------------------------------------------------- /test/data/kodim15_192x128_01p_yuv420_8b.yuv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/test/data/kodim15_192x128_01p_yuv420_8b.yuv -------------------------------------------------------------------------------- /test/data/kodim15_192x128_01p_yuv444_10b.yuv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/test/data/kodim15_192x128_01p_yuv444_10b.yuv -------------------------------------------------------------------------------- /test/data/kodim15_192x128_01p_yuv444_8b.yuv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/test/data/kodim15_192x128_01p_yuv444_8b.yuv -------------------------------------------------------------------------------- /docs/source/assets/kodak/all_complexity_dec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/kodak/all_complexity_dec.png -------------------------------------------------------------------------------- /docs/source/assets/kodak/perf_decoding_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/kodak/perf_decoding_time.png -------------------------------------------------------------------------------- /test/data/D-BQSquare_224x128_60p_yuv420_8b.yuv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/test/data/D-BQSquare_224x128_60p_yuv420_8b.yuv -------------------------------------------------------------------------------- /docs/source/assets/clic20-pro-valid/concat_img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/clic20-pro-valid/concat_img.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/all_complexity_classB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/all_complexity_classB.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/all_complexity_classC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/all_complexity_classC.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/all_complexity_classD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/all_complexity_classD.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/all_complexity_classE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/all_complexity_classE.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/all_complexity_classF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/all_complexity_classF.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/concat_img_classBCDEF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/concat_img_classBCDEF.png -------------------------------------------------------------------------------- /docs/source/assets/kodak/perf_complexity_dec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/kodak/perf_complexity_dec.png -------------------------------------------------------------------------------- /docs/source/assets/kodak/perf_complexity_enc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/kodak/perf_complexity_enc.png -------------------------------------------------------------------------------- /docs/source/assets/clic20-pro-valid/all_complexity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/clic20-pro-valid/all_complexity.png -------------------------------------------------------------------------------- /docs/source/assets/encoding-time/encoding-time-clic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/encoding-time/encoding-time-clic.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/all_complexity_classBCDEF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/all_complexity_classBCDEF.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/all_complexity_dec_classB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/all_complexity_dec_classB.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/all_complexity_dec_classC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/all_complexity_dec_classC.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/all_complexity_dec_classD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/all_complexity_dec_classD.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/all_complexity_dec_classE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/all_complexity_dec_classE.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/all_complexity_dec_classF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/all_complexity_dec_classF.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_complexity_dec_classB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_complexity_dec_classB.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_complexity_dec_classC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_complexity_dec_classC.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_complexity_dec_classD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_complexity_dec_classD.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_complexity_dec_classE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_complexity_dec_classE.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_complexity_dec_classF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_complexity_dec_classF.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_complexity_enc_classB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_complexity_enc_classB.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_complexity_enc_classC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_complexity_enc_classC.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_complexity_enc_classD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_complexity_enc_classD.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_complexity_enc_classE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_complexity_enc_classE.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_complexity_enc_classF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_complexity_enc_classF.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_decoding_time_classB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_decoding_time_classB.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_decoding_time_classC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_decoding_time_classC.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_decoding_time_classD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_decoding_time_classD.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_decoding_time_classE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_decoding_time_classE.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_decoding_time_classF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_decoding_time_classF.png -------------------------------------------------------------------------------- /test/data/D-BQSquare-3frames_224x128_60p_yuv420_8b.yuv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/test/data/D-BQSquare-3frames_224x128_60p_yuv420_8b.yuv -------------------------------------------------------------------------------- /test/data/D-BQSquare-5frames_224x128_60p_yuv420_8b.yuv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/test/data/D-BQSquare-5frames_224x128_60p_yuv420_8b.yuv -------------------------------------------------------------------------------- /docs/source/assets/encoding-time/encoding-time-jvet-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/encoding-time/encoding-time-jvet-b.png -------------------------------------------------------------------------------- /docs/source/assets/encoding-time/encoding-time-jvet-e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/encoding-time/encoding-time-jvet-e.png -------------------------------------------------------------------------------- /docs/source/assets/encoding-time/encoding-time-kodak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/encoding-time/encoding-time-kodak.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/all_complexity_dec_classBCDEF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/all_complexity_dec_classBCDEF.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_decoding_time_classBCDEF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_decoding_time_classBCDEF.png -------------------------------------------------------------------------------- /samples/bitstreams/B-Cactus_1920x1080_50p_yuv420_8b.cool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/samples/bitstreams/B-Cactus_1920x1080_50p_yuv420_8b.cool -------------------------------------------------------------------------------- /docs/source/assets/clic20-pro-valid/all_complexity_dec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/clic20-pro-valid/all_complexity_dec.png -------------------------------------------------------------------------------- /docs/source/assets/clic20-pro-valid/perf_complexity_dec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/clic20-pro-valid/perf_complexity_dec.png -------------------------------------------------------------------------------- /docs/source/assets/clic20-pro-valid/perf_complexity_enc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/clic20-pro-valid/perf_complexity_enc.png -------------------------------------------------------------------------------- /docs/source/assets/clic20-pro-valid/perf_decoding_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/clic20-pro-valid/perf_decoding_time.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_complexity_dec_classBCDEF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_complexity_dec_classBCDEF.png -------------------------------------------------------------------------------- /docs/source/assets/jvet/perf_complexity_enc_classBCDEF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/jvet/perf_complexity_enc_classBCDEF.png -------------------------------------------------------------------------------- /samples/bitstreams/C-BasketballDrill_832x480_50p_yuv420_8b.cool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/samples/bitstreams/C-BasketballDrill_832x480_50p_yuv420_8b.cool -------------------------------------------------------------------------------- /docs/source/assets/video-ra-jvet-c/rd-C-BQMall_832x480_60p_yuv420_8b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/video-ra-jvet-c/rd-C-BQMall_832x480_60p_yuv420_8b.png -------------------------------------------------------------------------------- /docs/source/assets/video-ra-jvet-c/rd-C-PartyScene_832x480_50p_yuv420_8b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/video-ra-jvet-c/rd-C-PartyScene_832x480_50p_yuv420_8b.png -------------------------------------------------------------------------------- /docs/source/assets/video-ra-jvet-c/rd-C-RaceHorses_832x480_30p_yuv420_8b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/video-ra-jvet-c/rd-C-RaceHorses_832x480_30p_yuv420_8b.png -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/io/io.rst: -------------------------------------------------------------------------------- 1 | I/O 2 | === 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.io.io 8 | 9 | .. autofunction:: load_frame_data_from_file 10 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/training/train.rst: -------------------------------------------------------------------------------- 1 | Train 2 | ===== 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.training.train 8 | 9 | .. autofunction:: train 10 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/training/warmup.rst: -------------------------------------------------------------------------------- 1 | Train 2 | ===== 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.training.warmup 8 | 9 | .. autofunction:: warmup 10 | -------------------------------------------------------------------------------- /cfg/dec/intra/vlop.cfg: -------------------------------------------------------------------------------- 1 | arm_residue = 8,1 2 | layers_synthesis_residue = 8-1-linear-relu,X-1-linear-none,X-3-residual-none 3 | n_ft_per_res_residue = 1,1,1,1,1,1,1 4 | ups_k_size_residue = 8 5 | ups_preconcat_k_size_residue = 7 -------------------------------------------------------------------------------- /cfg/dec/residue/vlop.cfg: -------------------------------------------------------------------------------- 1 | arm_residue = 8,1 2 | layers_synthesis_residue = 8-1-linear-relu,X-1-linear-none,X-3-residual-none 3 | n_ft_per_res_residue = 1,1,1,1,1,1,1 4 | ups_k_size_residue = 8 5 | ups_preconcat_k_size_residue = 7 -------------------------------------------------------------------------------- /docs/source/assets/video-ra-jvet-c/rd-C-BasketballDrill_832x480_50p_yuv420_8b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Orange-OpenSource/Cool-Chic/HEAD/docs/source/assets/video-ra-jvet-c/rd-C-BasketballDrill_832x480_50p_yuv420_8b.png -------------------------------------------------------------------------------- /cfg/dec/intra/hop.cfg: -------------------------------------------------------------------------------- 1 | arm_residue = 16,2 2 | layers_synthesis_residue = 48-1-linear-relu,X-1-linear-none,X-3-residual-relu,X-3-residual-none 3 | n_ft_per_res_residue = 1,1,1,1,1,1,1 4 | ups_k_size_residue = 8 5 | ups_preconcat_k_size_residue = 7 -------------------------------------------------------------------------------- /cfg/dec/intra/lop.cfg: -------------------------------------------------------------------------------- 1 | arm_residue = 8,2 2 | layers_synthesis_residue = 16-1-linear-relu,X-1-linear-none,X-3-residual-relu,X-3-residual-none 3 | n_ft_per_res_residue = 1,1,1,1,1,1,1 4 | ups_k_size_residue = 8 5 | ups_preconcat_k_size_residue = 7 6 | -------------------------------------------------------------------------------- /cfg/dec/intra/mop.cfg: -------------------------------------------------------------------------------- 1 | arm_residue = 16,2 2 | layers_synthesis_residue = 16-1-linear-relu,X-1-linear-none,X-3-residual-relu,X-3-residual-none 3 | n_ft_per_res_residue = 1,1,1,1,1,1,1 4 | ups_k_size_residue = 8 5 | ups_preconcat_k_size_residue = 7 -------------------------------------------------------------------------------- /cfg/dec/residue/hop.cfg: -------------------------------------------------------------------------------- 1 | arm_residue = 16,2 2 | layers_synthesis_residue = 48-1-linear-relu,X-1-linear-none,X-3-residual-relu,X-3-residual-none 3 | n_ft_per_res_residue = 1,1,1,1,1,1,1 4 | ups_k_size_residue = 8 5 | ups_preconcat_k_size_residue = 7 -------------------------------------------------------------------------------- /cfg/dec/residue/mop.cfg: -------------------------------------------------------------------------------- 1 | arm_residue = 16,2 2 | layers_synthesis_residue = 16-1-linear-relu,X-1-linear-none,X-3-residual-relu,X-3-residual-none 3 | n_ft_per_res_residue = 1,1,1,1,1,1,1 4 | ups_k_size_residue = 8 5 | ups_preconcat_k_size_residue = 7 -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/training/quantizemodel.rst: -------------------------------------------------------------------------------- 1 | Train 2 | ===== 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.training.quantizemodel 8 | 9 | .. autofunction:: quantize_model 10 | -------------------------------------------------------------------------------- /cfg/dec/motion/lop.cfg: -------------------------------------------------------------------------------- 1 | arm_motion = 8,1 2 | layers_synthesis_motion = 8-1-linear-relu,X-1-linear-none,X-3-residual-none 3 | n_ft_per_res_motion = 0,0,1,1,1,1,1 4 | ups_k_size_motion = 8 5 | ups_preconcat_k_size_motion = 7 6 | warp_filter_size = 8 7 | -------------------------------------------------------------------------------- /cfg/dec/motion/mop.cfg: -------------------------------------------------------------------------------- 1 | arm_motion = 8,2 2 | layers_synthesis_motion = 16-1-linear-relu,X-1-linear-none,X-3-residual-none 3 | n_ft_per_res_motion = 0,0,1,1,1,1,1 4 | ups_k_size_motion = 8 5 | ups_preconcat_k_size_motion = 7 6 | warp_filter_size = 8 7 | -------------------------------------------------------------------------------- /cfg/dec/residue/lop.cfg: -------------------------------------------------------------------------------- 1 | arm_residue = 8,2 2 | layers_synthesis_residue = 16-1-linear-relu,X-1-linear-none,X-3-residual-relu,X-3-residual-none 3 | n_ft_per_res_residue = 1,1,1,1,1,1,1 4 | ups_k_size_residue = 8 5 | ups_preconcat_k_size_residue = 7 6 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/nnquant/quantizemodel.rst: -------------------------------------------------------------------------------- 1 | Quantize Model 2 | ============== 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.nnquant.quantizemodel 8 | 9 | .. autofunction:: quantize_model 10 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/io/format/png.rst: -------------------------------------------------------------------------------- 1 | PNG Format 2 | ========== 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.io.format.png 8 | 9 | .. autofunction:: read_png 10 | 11 | .. autofunction:: write_png 12 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/io/format/ppm.rst: -------------------------------------------------------------------------------- 1 | PPM Format 2 | ========== 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.io.format.ppm 8 | 9 | .. autofunction:: read_ppm 10 | 11 | .. autofunction:: write_ppm 12 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=42", "pybind11>=2.6.1"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [tool.pytest.ini_options] 6 | pythonpath = [ 7 | "coolchic", 8 | "scripts" 9 | ] 10 | testpaths = [ 11 | "test" 12 | ] -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/training/test.rst: -------------------------------------------------------------------------------- 1 | Test 2 | ==== 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.training.test 8 | 9 | .. autofunction:: test 10 | 11 | .. autoclass:: FrameEncoderLogs 12 | :members: 13 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/component/intercoding/raft.rst: -------------------------------------------------------------------------------- 1 | RAFT 2 | ============================ 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.component.intercoding.raft 8 | 9 | .. autofunction:: get_raft_optical_flow 10 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/training/loss.rst: -------------------------------------------------------------------------------- 1 | Loss 2 | ==== 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.training.loss 8 | 9 | .. autofunction:: loss_function 10 | 11 | .. autoclass:: LossFunctionOutput 12 | :members: 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | images/ 3 | venv/ 4 | *.pyc 5 | *.pt 6 | *.png 7 | *.out 8 | 9 | docs/build/ 10 | .DS_Store 11 | __pycache__/ 12 | *.py[cod] 13 | *$py.class 14 | *.nfs* 15 | 16 | test/test-workdir/ 17 | test/out/ 18 | venv/ 19 | 20 | coolchic/CCLIB/ 21 | coolchic.egg-info/ 22 | *.so -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/component/intercoding/globalmotion.rst: -------------------------------------------------------------------------------- 1 | Global motion estimation 2 | ======================== 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.component.intercoding.globalmotion 8 | 9 | .. autofunction:: get_global_translation 10 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/component/video.rst: -------------------------------------------------------------------------------- 1 | Video Encoder 2 | ================= 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.component.video 8 | 9 | .. autoclass:: VideoEncoder 10 | :members: 11 | 12 | .. autofunction:: load_video_encoder 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/nnquant/expgolomb.rst: -------------------------------------------------------------------------------- 1 | Exponential-Golomb Code 2 | ======================= 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.nnquant.expgolomb 8 | 9 | .. autofunction:: measure_expgolomb_rate 10 | 11 | .. autofunction:: exp_golomb_nbins 12 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/component/core/synthesis.rst: -------------------------------------------------------------------------------- 1 | Synthesis 2 | ========= 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.component.core.synthesis 8 | 9 | .. autoclass:: Synthesis 10 | :members: 11 | 12 | .. autoclass:: SynthesisConv2d 13 | :members: 14 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/component/core/arm.rst: -------------------------------------------------------------------------------- 1 | Auto-Regressive Module (ARM) 2 | ============================ 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.component.core.arm 8 | 9 | .. autoclass:: Arm 10 | :members: 11 | 12 | .. autoclass:: ArmLinear 13 | :members: 14 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/component/core/quantizer.rst: -------------------------------------------------------------------------------- 1 | Quantizer 2 | ========= 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.component.core.quantizer 8 | 9 | .. autofunction:: quantize 10 | 11 | .. autofunction:: softround 12 | 13 | .. autofunction:: generate_kumaraswamy_noise 14 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/utils/index.rst: -------------------------------------------------------------------------------- 1 | Utils 2 | ===== 3 | 4 | ``Utils`` contains helper functions used to manage the encoding. 5 | 6 | * ``CodingStructure`` is an abstraction representing how a video is encoded 7 | *i.e.* intra period, hierarchical GOP etc. 8 | 9 | .. toctree:: 10 | 11 | codingstructure 12 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/nnquant/index.rst: -------------------------------------------------------------------------------- 1 | Neural network quantization (``nnquant``) 2 | ========================================= 3 | 4 | * ``quantizemodel.py`` is called at the end of the training to quantize the 5 | neural networks rate 6 | 7 | 8 | .. toctree:: 9 | 10 | quantizemodel 11 | expgolomb 12 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/component/intercoding/index.rst: -------------------------------------------------------------------------------- 1 | Intercoding 2 | =========== 3 | 4 | Functions related to inter coding i.e. raft-based motion estimation, warping a 5 | frame with an optical flow, finding a global translation between two frames. 6 | 7 | .. toctree:: 8 | 9 | globalmotion 10 | raft 11 | warp 12 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/component/frame.rst: -------------------------------------------------------------------------------- 1 | Frame Encoder 2 | ================= 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.component.frame 8 | 9 | .. autoclass:: FrameEncoder 10 | :members: 11 | 12 | .. autoclass:: FrameEncoderOutput 13 | :members: 14 | :exclude-members: __init__ 15 | 16 | .. autofunction:: load_frame_encoder 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/index.rst: -------------------------------------------------------------------------------- 1 | Encoder 2 | ======= 3 | 4 | The encoder of Cool-chic is based on PyTorch. Its role is to learn the latent 5 | representation and the tiny neural networks allowing to efficiently decode each 6 | frame. 7 | 8 | .. toctree:: 9 | 10 | component 11 | io 12 | nnquant 13 | training 14 | utils 15 | 16 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/component/core/upsampling.rst: -------------------------------------------------------------------------------- 1 | Upsampling 2 | ========== 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.component.core.upsampling 8 | 9 | .. autoclass:: Upsampling 10 | :members: 11 | 12 | .. autoclass:: UpsamplingSeparableSymmetricConvTranspose2d 13 | :members: 14 | 15 | .. autoclass:: UpsamplingSeparableSymmetricConv2d 16 | :members: 17 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/component/intercoding/warp.rst: -------------------------------------------------------------------------------- 1 | Warping an image with an optical flow 2 | ===================================== 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.component.intercoding.warp 8 | 9 | .. autoclass:: Warper 10 | :members: 11 | 12 | .. autoclass:: WarpParameter 13 | :members: 14 | :exclude-members: __init__ 15 | 16 | .. autofunction:: vanilla_warp_fn 17 | -------------------------------------------------------------------------------- /coolchic/enc/io/types.py: -------------------------------------------------------------------------------- 1 | # Software Name: Cool-Chic 2 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 3 | # SPDX-License-Identifier: BSD 3-Clause "New" 4 | # 5 | # This software is distributed under the BSD-3-Clause license. 6 | # 7 | # Authors: see CONTRIBUTORS.md 8 | 9 | 10 | from typing import Literal 11 | 12 | 13 | FRAME_DATA_TYPE = Literal["rgb", "yuv420", "yuv444", "flow"] 14 | POSSIBLE_BITDEPTH = Literal[8, 9, 10, 11, 12, 13, 14, 15, 16] 15 | -------------------------------------------------------------------------------- /coolchic/cpp/ups_cpu.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "common.h" 3 | #include "frame-memory.h" 4 | #include "ups_cpu.h" 5 | 6 | #define KS 7 7 | #define UPSNAME ups_refine_ks7_cpu 8 | #include "ups_refine_cpu.hpp" 9 | 10 | #define UPSNAME ups_refine_ksX_cpu 11 | #include "ups_refine_cpu.hpp" 12 | 13 | #define KS 8 14 | #define UPSNAME ups_upsample_ks8_cpu 15 | #include "ups_upsample_cpu.hpp" 16 | 17 | #define UPSNAME ups_upsample_ksX_cpu 18 | #include "ups_upsample_cpu.hpp" 19 | -------------------------------------------------------------------------------- /coolchic/enc/io/format/data_type.py: -------------------------------------------------------------------------------- 1 | # Software Name: Cool-Chic 2 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 3 | # SPDX-License-Identifier: BSD 3-Clause "New" 4 | # 5 | # This software is distributed under the BSD-3-Clause license. 6 | # 7 | # Authors: see CONTRIBUTORS.md 8 | 9 | 10 | from typing import Literal 11 | 12 | 13 | FRAME_DATA_TYPE = Literal["rgb", "yuv420", "yuv444"] 14 | POSSIBLE_BITDEPTH = Literal[8, 9, 10, 11, 12, 13, 14, 15, 16] 15 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/io/index.rst: -------------------------------------------------------------------------------- 1 | Input / Output 2 | ============== 3 | 4 | The ``io`` submodule gather the different functions used to read and write 5 | images and video frames. 6 | 7 | * ``io.py`` contains the only function used to load a frame from a file. 8 | 9 | * ``format/`` implements the read & write functions for YUV, PNG and PPM format. 10 | 11 | .. toctree:: 12 | 13 | io 14 | format 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/component/coolchic.rst: -------------------------------------------------------------------------------- 1 | Cool-chic Encoder 2 | ================= 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.component.coolchic 8 | 9 | .. autoclass:: CoolChicEncoder 10 | :members: 11 | 12 | .. autoclass:: CoolChicEncoderParameter 13 | :members: 14 | :exclude-members: __init__ 15 | 16 | .. autoclass:: CoolChicEncoderOutput 17 | :members: 18 | :exclude-members: __init__ 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/component/core/index.rst: -------------------------------------------------------------------------------- 1 | Core modules 2 | ============ 3 | 4 | The core modules of Cool-chic are the Auto-Regressive Module (ARM), the 5 | quantizer, the upsampling and the synthesis. 6 | :doc:`Go here <../../../../image_compression/architecture>` for more information about 7 | how these modules are related. 8 | 9 | .. toctree:: 10 | 11 | arm 12 | quantizer 13 | upsampling 14 | synthesis 15 | -------------------------------------------------------------------------------- /.github/workflows/sanity-check.yml: -------------------------------------------------------------------------------- 1 | name: sanity_check 2 | 3 | on: [push] 4 | 5 | jobs: 6 | 7 | sanity-check: 8 | runs-on: ubuntu-latest 9 | defaults: 10 | run: 11 | working-directory: ./ 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-python@v5 15 | with: 16 | python-version: '3.10' 17 | cache: 'pip' # caching pip dependencies 18 | - run: pip install -e . 19 | - run: python3 -m test.sanity_check 20 | -------------------------------------------------------------------------------- /docs/source/video_compression/encoding.rst: -------------------------------------------------------------------------------- 1 | Encoding a video frame 2 | """""""""""""""""""""" 3 | 4 | Inter frame encoding have an additional training stage: the pre-training of the 5 | motion decoder to imitate an optical flow obtained by RAFT, an off-the-shelf 6 | optical flow estimator. The duration of this training phase is set by the 7 | ``--n_itr_pretrain_motion`` parameter. 8 | 9 | See the :ref:`video coding example script ` for an example 10 | of how videos are encoded using Cool-chic. 11 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/training/preset.rst: -------------------------------------------------------------------------------- 1 | Encoding Presets 2 | ================ 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.training.presets 8 | 9 | .. autoclass:: Preset 10 | :members: 11 | :exclude-members: __init__ 12 | 13 | 14 | .. autoclass:: Warmup 15 | :members: 16 | :exclude-members: __init__ 17 | 18 | 19 | .. autoclass:: WarmupPhase 20 | :members: 21 | :exclude-members: __init__ 22 | 23 | 24 | .. autoclass:: TrainerPhase 25 | :members: 26 | :exclude-members: __init__ 27 | -------------------------------------------------------------------------------- /docs/source/results/video/index.rst: -------------------------------------------------------------------------------- 1 | Video coding performance 2 | ======================== 3 | 4 | We provide comprehensive experimental results demonstrating the compression 5 | performance of Cool-chic, its low decoding complexity and the associated 6 | encoding complexity. 7 | 8 | We also provide some already encoded bitstreams in ``samples/bitstream/`` so 9 | that everybody can decode them to try out our fast CPU-only neural decoder. 10 | 11 | .. toctree:: 12 | :maxdepth: 1 13 | :caption: Video 14 | :hidden: 15 | 16 | Compression performance 17 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/io/format/yuv.rst: -------------------------------------------------------------------------------- 1 | YUV Format 2 | ========== 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.io.format.yuv 8 | 9 | .. autoclass:: DictTensorYUV 10 | :members: 11 | 12 | .. autofunction:: read_yuv 13 | 14 | .. autofunction:: write_yuv 15 | 16 | .. autofunction:: rgb2yuv 17 | 18 | .. autofunction:: yuv2rgb 19 | 20 | .. autofunction:: yuv_dict_clamp 21 | 22 | .. autofunction:: yuv_dict_to_device 23 | 24 | .. autofunction:: convert_444_to_420 25 | 26 | .. autofunction:: convert_420_to_444 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/io/format/index.rst: -------------------------------------------------------------------------------- 1 | Format 2 | ====== 3 | 4 | The ``format`` submodule gather the different functions used to read and write 5 | images and video frames with different formats. 6 | 7 | * ``yuv.py`` for `YUV data `_ files. 8 | 9 | * ``png.py`` for PNG data 10 | 11 | * ``ppm.py`` for `PPM data `_ 12 | 13 | * ``data_type.py`` defines some useful types. 14 | 15 | .. toctree:: 16 | 17 | yuv 18 | png 19 | ppm 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /coolchic/cpp/common_randomness.h: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | #ifndef COMMON_RANDOMNESS 11 | #define COMMON_RANDOMNESS 12 | 13 | class common_randomness{ 14 | 15 | public: 16 | float grand(); 17 | short grand16(); 18 | private: 19 | unsigned long int seed = 18101995; // nice seed 20 | }; 21 | 22 | #endif // COMMON_RANDOMNESS 23 | -------------------------------------------------------------------------------- /coolchic/enc/training/metrics/mse.py: -------------------------------------------------------------------------------- 1 | # Software Name: Cool-Chic 2 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 3 | # SPDX-License-Identifier: BSD 3-Clause "New" 4 | # 5 | # This software is distributed under the BSD-3-Clause license. 6 | # 7 | # Authors: see CONTRIBUTORS.md 8 | 9 | import math 10 | from torch import Tensor 11 | 12 | 13 | def mse_fn(x: Tensor, y: Tensor) -> Tensor: 14 | return (x - y).square().mean() 15 | 16 | def dist_to_db(dist: float, max_db: float = 100) -> float: 17 | min_dist = 10 ** (-max_db / 10) 18 | dist = max(dist, min_dist) 19 | return -10 * math.log10(dist) 20 | -------------------------------------------------------------------------------- /docs/source/_templates/partials/webfonts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /coolchic/cpp/warp.h: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | template 11 | void warp_ntaps(struct frame_memory

&warp_result, 12 | struct frame_memory

const &frame_residual, struct frame_memory

const &frame_motion, struct frame_memory

const &ref, int global_flow[2], 13 | int raw_xyidx, int raw_gainidx, bool add_residue, int ntaps, int motion_blksz_shift, int motion_q); 14 | -------------------------------------------------------------------------------- /coolchic/cpp/warp_cpu.h: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | template 11 | void warp_ntaps_cpu(struct frame_memory

&warp_result, 12 | struct frame_memory

const &frame_residual, struct frame_memory

const &frame_motion, struct frame_memory

const &ref, int global_flow[2], 13 | int raw_xyidx, int raw_gainidx, bool add_residue, int ntaps, int motion_blksz_shift, int motion_q); 14 | -------------------------------------------------------------------------------- /docs/source/results/image/index.rst: -------------------------------------------------------------------------------- 1 | Image coding performance 2 | ======================== 3 | 4 | We provide comprehensive experimental results demonstrating the compression 5 | performance of Cool-chic, its low decoding complexity and the associated 6 | encoding complexity. 7 | 8 | We also provide some already encoded bitstreams in ``samples/bitstream/`` so 9 | that everybody can decode them to try out our fast CPU-only neural decoder. 10 | 11 | 12 | .. toctree:: 13 | :maxdepth: 1 14 | :caption: Image 15 | :hidden: 16 | 17 | Compression performance 18 | Decoding complexity 19 | Encoding complexity 20 | -------------------------------------------------------------------------------- /coolchic/cpp/warp_avx2.h: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | template 11 | void warp_ntaps_avx2(struct frame_memory

&warp_result, 12 | struct frame_memory

const &frame_residual, struct frame_memory

const &frame_motion, struct frame_memory

const &ref, int global_flow[2], 13 | int raw_xyidx, int raw_gainidx, bool add_residue, int ntaps, int motion_blksz_shift, int motion_q); 14 | -------------------------------------------------------------------------------- /docs/source/code_documentation/encoder/utils/codingstructure.rst: -------------------------------------------------------------------------------- 1 | Coding Structure 2 | ================= 3 | 4 | .. autosummary:: 5 | :toctree: generated 6 | 7 | .. currentmodule:: enc.utils.codingstructure 8 | 9 | .. autoclass:: CodingStructure 10 | :members: 11 | :exclude-members: __init__ 12 | 13 | .. autoclass:: Frame 14 | :members: 15 | :exclude-members: __init__ 16 | 17 | .. autoclass:: FrameData 18 | :members: 19 | :exclude-members: __init__ 20 | 21 | .. .. autoclass:: DictTensorYUV 22 | .. :members: 23 | 24 | .. .. autofunction:: yuv_dict_to_device 25 | 26 | .. .. autofunction:: convert_444_to_420 27 | 28 | .. .. autofunction:: convert_420_to_444 29 | -------------------------------------------------------------------------------- /coolchic/cpp/ups_cpu.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | template 4 | void ups_refine_ks7_cpu(int ks, P *kw, frame_memory

&in, frame_memory

&out, int ups_src_precision, frame_memory

&tmp); 5 | template 6 | void ups_refine_ksX_cpu(int ks, P *kw, frame_memory

&in, frame_memory

&out, int ups_src_precision, frame_memory

&tmp); 7 | 8 | template 9 | void ups_upsample_ks8_cpu(int ksx2, P *kw, frame_memory

&in, frame_memory

&out, int out_plane, int ups_src_precision, frame_memory

&tmp); 10 | template 11 | void ups_upsample_ksX_cpu(int ksx2, P *kw, frame_memory

&in, frame_memory

&out, int out_plane, int ups_src_precision, frame_memory

&tmp); 12 | -------------------------------------------------------------------------------- /coolchic/cpp/ups_avx2.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "common.h" 3 | #include "frame-memory.h" 4 | #include "ups_cpu.h" 5 | #include 6 | 7 | #define KS 7 8 | #define UPSNAME ups_refine_ks7_avx2 9 | #include "ups_refine_avx2.hpp" 10 | 11 | #define UPSNAME ups_refine_ksX_avx2 12 | #include "ups_refine_avx2.hpp" 13 | 14 | #define KS 8 15 | #define UPS_SRC_PRECISION ARM_PRECISION 16 | #define UPSNAME ups_upsample_ks8_ARMPREC_avx2 17 | #include "ups_upsample_avx2.hpp" 18 | 19 | #define KS 8 20 | #define UPS_SRC_PRECISION UPS_PRECISION 21 | #define UPSNAME ups_upsample_ks8_UPSPREC_avx2 22 | #include "ups_upsample_avx2.hpp" 23 | 24 | #define UPSNAME ups_upsample_ksX_avx2 25 | #include "ups_upsample_avx2.hpp" 26 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /coolchic/cpp/synblend_avx2.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | void syn_blend1_avx2(int h_in, int w_in, int stride_in, int plane_stride_in, int N_INOUT, int32_t *in, int32_t blend_val, int32_t *out) 11 | { 12 | printf("should not be here\n"); 13 | exit(1); 14 | } 15 | 16 | void syn_blend2_avx2(int h_in, int w_in, int stride_in, int plane_stride_in, int N_INOUT, int32_t *in, int32_t blend_val_in, int32_t *out, int32_t blend_val_out) 17 | { 18 | printf("should not be here\n"); 19 | exit(1); 20 | } 21 | -------------------------------------------------------------------------------- /docs/source/results/image/reproduce_results.rst: -------------------------------------------------------------------------------- 1 | Reproduce our best results 2 | ========================== 3 | 4 | We provide already encoded files as bitstreams in 5 | ``results/image//`` where ```` can be ``kodak``, 6 | ``clic20-pro-valid``, ``jvet``. 7 | 8 | 9 | These bitstreams allow to reproduce the results stated above qnd reflect the 10 | current best rate-distortion results achievable with Cool-chic. 11 | 12 | For each dataset, a script decodes all the bitstreams. 13 | 14 | .. code:: bash 15 | 16 | (venv) python results/decode_one_dataset.py image # Can take a few minutes 17 | 18 | 19 | The file ``results/image//results.tsv`` provides the 20 | results that should be obtained. 21 | -------------------------------------------------------------------------------- /docs/source/image_compression/decoding_images.rst: -------------------------------------------------------------------------------- 1 | Decoding images with Cool-chic 2 | =============================== 3 | 4 | In order to offer fast decoding, Cool-chic relies on a C API re-implementing 5 | efficiently all the components of the decoder *i.e* ARM, Upsampling, Synthesis. 6 | 7 | The following script is used to decode image with Cool-chic. We provide a few 8 | already encoded bitstreams, ready to be decoded in ``samples/bitstreams/``. 9 | 10 | 11 | .. code:: bash 12 | 13 | (venv) ~/Cool-Chic$ python coolchic/decode.py \ 14 | -i=samples/bitstream/kodim14.cool \ 15 | -o=decoded-kodim14.ppm \ 16 | --verbosity=1 17 | 18 | Note that Cool-Chic outputs either `PPM 19 | `_ (and not PNG!) or `YUV 20 | `_ files. 21 | -------------------------------------------------------------------------------- /coolchic/cpp/arm_cpu.h: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | void custom_conv_11_int32_cpu_X_X_X(weights_biases *kwtX_n_n, weights_biases *kbX_n, // kwt0_16_16 -- kernel weights, transposed. 11 | weights_biases *kwOUT_n_2, weights_biases *kbOUT_2, 12 | int32_t *context_indicies, int32_t n_contexts, int n_hidden_layers, 13 | int32_t *SRC, 14 | int src_h, int src_w, int src_pad, 15 | BACContext &bac_context 16 | ); 17 | -------------------------------------------------------------------------------- /docs/source/results/index.rst: -------------------------------------------------------------------------------- 1 | Cool-chic experimental results 2 | ============================== 3 | 4 | We provide comprehensive experimental results demonstrating the compression 5 | performance of Cool-chic, its low decoding complexity and the associated 6 | encoding complexity. 7 | 8 | We also provide some already encoded bitstreams in ``samples/bitstream/`` so 9 | that everybody can decode them to try out our fast CPU-only neural decoder. 10 | 11 | 12 | .. toctree:: 13 | :maxdepth: 1 14 | :caption: Image 15 | :hidden: 16 | 17 | Compression performance 18 | Decoding complexity 19 | Encoding complexity 20 | 21 | .. toctree:: 22 | :maxdepth: 1 23 | :caption: Video 24 | :hidden: 25 | 26 | Compression performance

&in, frame_memory

&out, int ups_src_precision, frame_memory

&tmp); 13 | template 14 | void ups_refine_ksX_avx2(int ks, P *kw, frame_memory

&in, frame_memory

&out, int ups_src_precision, frame_memory

&tmp); 15 | template 16 | void ups_upsample_ks8_UPSPREC_avx2(int ksx2, P *kw, frame_memory

&in, frame_memory

&out, int out_plane, int ups_src_precision, frame_memory

&tmp); 17 | template 18 | void ups_upsample_ks8_ARMPREC_avx2(int ksx2, P *kw, frame_memory

&in, frame_memory

&out, int out_plane, int ups_src_precision, frame_memory

&tmp); 19 | template 20 | void ups_upsample_ksX_avx2(int ksx2, P *kw, frame_memory

&in, frame_memory

&out, int out_plane, int ups_src_precision, frame_memory

&tmp); 21 | -------------------------------------------------------------------------------- /.github/workflows/static-pages.yml: -------------------------------------------------------------------------------- 1 | name: documentation 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | 5 | permissions: 6 | contents: write 7 | pages: write 8 | id-token: write 9 | 10 | 11 | jobs: 12 | # Single deploy job since we're just deploying 13 | deploy: 14 | environment: 15 | name: github-pages 16 | url: ${{ steps.deployment.outputs.page_url }} 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | - name: Install dependencies 22 | run: | 23 | pip install -U torch fvcore einops psutil torchvision sphinx shibuya sphinx-autodoc-typehints sphinx-copybutton sphinx-design 24 | - name: Sphinx build 25 | run: | 26 | PYTORCH_JIT=0 sphinx-build docs/source/ docs/build 27 | - name: Setup Pages 28 | uses: actions/configure-pages@v4 29 | - name: Upload artifact 30 | uses: actions/upload-pages-artifact@v3 31 | with: 32 | # Upload entire repository 33 | path: 'docs/build' 34 | - name: Deploy to GitHub Pages 35 | id: deployment 36 | uses: actions/deploy-pages@v4 37 | -------------------------------------------------------------------------------- /coolchic/enc/bitstream/utils.py: -------------------------------------------------------------------------------- 1 | # Software Name: Cool-Chic 2 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 3 | # SPDX-License-Identifier: BSD 3-Clause "New" 4 | # 5 | # This software is distributed under the BSD-3-Clause license. 6 | # 7 | # Authors: see CONTRIBUTORS.md 8 | 9 | def get_sub_bitstream_path( 10 | root_bitstream_path: str, 11 | counter_2d_latent: int, 12 | ) -> str: 13 | """Return the complete path of the sub-bistream corresponding to the 14 | -th 2D feature maps. This is use due to the fact that 15 | even 3D features are coded as independent 2D features. 16 | 17 | Args: 18 | root_bitstream_path (str): Root name of the bitstream 19 | counter_2d_latent (int): Index of 2D features. Let us suppose that we have 20 | two features maps, one is [1, 1, H, W] and the other is [1, 2, H/2, W/2]. 21 | The counter_2d_latent will be used to iterate on the **3** 2d features 22 | (one for the highest resolution, two for the smallest resolution). 23 | 24 | Returns: 25 | str: Complete bitstream path 26 | """ 27 | s = f'{root_bitstream_path}_{counter_2d_latent}' 28 | return s 29 | -------------------------------------------------------------------------------- /docs/source/code_documentation/overview.rst: -------------------------------------------------------------------------------- 1 | Cool-chic code at a glance 2 | ========================== 3 | 4 | Coolchic source code is organized as follows 5 | 6 | .. code:: none 7 | 8 | coolchic/ 9 | |___ enc/ 10 | | |___ component/ The different modules composing the Encoder 11 | | | |___ core/ The different NN (ARM, upsampling and synthesis) + quantizer 12 | | | |___ intercoding/ RAFT, warping function, global translation 13 | | | |___ coolchic.py Entire Cool-chic: Latent + ARM + upsampling + synthesis 14 | | | |___ frame.py Encode a frame with a cool-chic 15 | | | |___ video.py Encode one frame function, reference management 16 | | |___ io/ Read & write PNG, PPM and YUV 17 | | |___ training/ Train, test, quantize the models, loss, presets, warm-up 18 | | |___ nnquant/ Quantize neural networks at the end of the training 19 | | |___ utils/ Coding structure and various stuff. 20 | | |___ bitstream/ Write the bitstream from a trained model. 21 | | 22 | |___ dec/ Python interface with the C API for the decoder 23 | | 24 | |___ cpp/ Cool-chic C API for fast decoding & entropy coding 25 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2023-2025 Orange 2 | 3 | Redistribution and use in source and binary forms, with or without modification, 4 | are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation and/or 11 | other materials provided with the distribution. 12 | 13 | 3. Neither the name of the copyright holder nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without 15 | specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 21 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 24 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /toolbox/toolbox/yuv_concat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 5 | # SPDX-License-Identifier: BSD 3-Clause "New" 6 | # 7 | # This software is distributed under the BSD-3-Clause license. 8 | # 9 | # Authors: see CONTRIBUTORS.md 10 | 11 | 12 | """Extract the i-th frame of a YUV file and save it somewhere""" 13 | 14 | import argparse 15 | import subprocess 16 | from typing import List 17 | 18 | 19 | def concat_frames(input_path: List[str], output_path: str) -> None: 20 | """Concatenate a list of yuv files to a single one. The frame order 21 | follows the ordering of the list of paths. 22 | 23 | Args: 24 | input_path (List[str]): Path of the yuv files to be concatenated 25 | output_path (str): Path of the resulting yuv file 26 | """ 27 | assert input_path, "You must provide at least one input_path" 28 | 29 | cmd = "cat " 30 | for input_path_i in input_path: 31 | cmd += f"{input_path_i} " 32 | cmd += f" > {output_path}" 33 | 34 | subprocess.call(cmd, shell=True) 35 | 36 | 37 | if __name__ == "__main__": 38 | parser = argparse.ArgumentParser() 39 | parser.add_argument( 40 | "-i", 41 | "--input", 42 | type=str, 43 | required=True, 44 | help="Path of the input videos to concatenate, separated by comas. E.g" 45 | " /path/to/videoA.yuv,/path/to/videoB.yuv", 46 | ) 47 | parser.add_argument( 48 | "-o", 49 | "--output", 50 | help="Path of the output concatenated video", 51 | type=str, 52 | required=True, 53 | ) 54 | args = parser.parse_args() 55 | 56 | concat_frames(args.input.split(","), args.output) 57 | -------------------------------------------------------------------------------- /coolchic/cpp/common_avx2.h: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | // Used by arm_avx2 and syn_avx2. 11 | 12 | // INT 13 | inline int32_t hsum_epi32_avx(__m128i x) 14 | { 15 | __m128i hi64 = _mm_unpackhi_epi64(x, x); // 3-operand non-destructive AVX lets us save a byte without needing a movdqa 16 | __m128i sum64 = _mm_add_epi32(hi64, x); 17 | __m128i hi32 = _mm_shuffle_epi32(sum64, _MM_SHUFFLE(2, 3, 0, 1)); // Swap the low two elements 18 | __m128i sum32 = _mm_add_epi32(sum64, hi32); 19 | return _mm_cvtsi128_si32(sum32); // movd 20 | } 21 | 22 | // only needs AVX2 23 | inline int32_t hsum_8x32(__m256i v) 24 | { 25 | __m128i sum128 = _mm_add_epi32( 26 | _mm256_castsi256_si128(v), 27 | _mm256_extracti128_si256(v, 1)); // silly GCC uses a longer AXV512VL instruction if AVX512 is enabled :/ 28 | return hsum_epi32_avx(sum128); 29 | } 30 | 31 | static inline float horizontal_add (__m256 a) { 32 | __m256 t1 = _mm256_hadd_ps(a,a); 33 | __m256 t2 = _mm256_hadd_ps(t1,t1); 34 | __m128 t3 = _mm256_extractf128_ps(t2,1); 35 | __m128 t4 = _mm_add_ss(_mm256_castps256_ps128(t2),t3); 36 | return _mm_cvtss_f32(t4); 37 | } 38 | 39 | inline void print_ps(__m256 reg, char const *msg = NULL) 40 | { 41 | float store[8]; 42 | _mm256_storeu_ps(&store[0], reg); 43 | if (msg != NULL) 44 | printf(" %s", msg); 45 | for (int i = 0; i < 8; i++) 46 | printf(" %g", store[i]); 47 | printf("\n"); 48 | } 49 | -------------------------------------------------------------------------------- /docs/source/getting_started/quickstart.rst: -------------------------------------------------------------------------------- 1 | Quickstart 2 | ========== 3 | 4 | Installing necessary packages 5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | .. attention:: 8 | 9 | The setup requires ``python >= 3.10``. It is presented here with Python 3.10 but 10 | should work with more recent versions. 11 | 12 | The first step is to install some necessary packages and to clone Cool-chic. We 13 | need to install ``python3.10-dev`` to compile and bind the Cool-chic C API. 14 | 15 | .. code:: bash 16 | 17 | # We need to get g++, python3.10-dev and pip to compile the Cool-chic 18 | # C API and bind it to python. 19 | ~$ sudo add-apt-repository -y ppa:deadsnakes/ppa && sudo apt update 20 | ~$ sudo apt install -y build-essential python3.10-dev pip g++ 21 | ~$ git clone https://github.com/Orange-OpenSource/Cool-Chic.git && cd Cool-Chic 22 | 23 | 24 | You should create a virtual environment when installing Cool-chic 25 | 26 | .. code:: bash 27 | 28 | ~/Cool-Chic$ python3.10 -m pip install virtualenv # Install virtual env if needed 29 | ~/Cool-Chic$ python3.10 -m virtualenv venv && source venv/bin/activate # Create and activate a virtual env named "venv" 30 | 31 | Cool-chic can then be installed through pip, which retrieves the required 32 | package (torch etc.) and compiles the Cool-chic C API. 33 | 34 | .. code:: bash 35 | 36 | (venv) ~/Cool-Chic/$ pip install -e . 37 | 38 | 39 | Sanity check 40 | ~~~~~~~~~~~~ 41 | 42 | A simple sanity check script is provided. It performs a very fast encoding of 43 | different image and video formats, write a bitstream and decode it. 44 | 45 | .. code:: bash 46 | 47 | (venv) ~/Cool-Chic$ python -m test.sanity_check 48 | 49 | 50 | You're good to go! 51 | ****************** 52 | -------------------------------------------------------------------------------- /coolchic/enc/io/format/png.py: -------------------------------------------------------------------------------- 1 | # Software Name: Cool-Chic 2 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 3 | # SPDX-License-Identifier: BSD 3-Clause "New" 4 | # 5 | # This software is distributed under the BSD-3-Clause license. 6 | # 7 | # Authors: see CONTRIBUTORS.md 8 | 9 | 10 | import os 11 | from typing import Tuple 12 | 13 | import numpy as np 14 | import torch 15 | from einops import rearrange 16 | from enc.io.types import POSSIBLE_BITDEPTH 17 | from PIL import Image 18 | from torch import Tensor 19 | from torchvision.transforms.functional import to_pil_image, to_tensor 20 | 21 | 22 | def read_png(file_path: str) -> Tuple[Tensor, POSSIBLE_BITDEPTH]: 23 | """Read a PNG file 24 | 25 | Args: 26 | file_path: Path of the png file to read. 27 | 28 | Returns: 29 | Image data [1, 3, H, W] in [0., 1.] and its bitdepth. 30 | """ 31 | 32 | assert os.path.isfile(file_path), f"No file found at {file_path}" 33 | 34 | data = to_tensor(Image.open(file_path)) 35 | data = rearrange(data, "c h w -> 1 c h w") 36 | 37 | # Bitdepth is always 8 when we read PNG through PIL? 38 | bitdepth = 8 39 | 40 | return data, bitdepth 41 | 42 | 43 | @torch.no_grad() 44 | def write_png(data: Tensor, file_path: str) -> None: 45 | """Save an image x into a PNG file. 46 | 47 | Args: 48 | x: Image to be saved 49 | file_path: Where to save the PNG files 50 | """ 51 | data = rearrange(data, "1 c h w -> h w c", c=3) 52 | 53 | assert len(data.shape) == 3 and data.shape[-1] == 3, ( 54 | f"Data shape must be [H, W, 3], found {data.shape}" 55 | ) 56 | 57 | data = np.clip(data.cpu().detach().numpy(), 0.0, 1.0) 58 | data = np.round(data * 255).astype(np.uint8) 59 | 60 | im = Image.fromarray(data, mode="RGB") 61 | im.save(file_path) 62 | -------------------------------------------------------------------------------- /LICENSE_CABAC.txt: -------------------------------------------------------------------------------- 1 | The copyright in this software is being made available under the BSD 2 | License, included below. This software may be subject to other third party 3 | and contributor rights, including patent rights, and no such rights are 4 | granted under this license.   5 | 6 | Copyright (c) 2010-2025, ITU/ISO/IEC 7 | All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | 12 | * Redistributions of source code must retain the above copyright notice, 13 | this list of conditions and the following disclaimer. 14 | * Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | * Neither the name of the ITU/ISO/IEC nor the names of its contributors may 18 | be used to endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /coolchic/enc/io/framedata.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass, field 2 | from enc.io.types import FRAME_DATA_TYPE, POSSIBLE_BITDEPTH 3 | from typing import Any, Tuple 4 | 5 | 6 | @dataclass 7 | class FrameData: 8 | """FrameData is a dataclass storing the actual pixel values of a frame and 9 | a few additional information about its size, bitdepth of color space. 10 | 11 | Args: 12 | bitdepth: Bitdepth, should be in``[8, 9, 10, 11, 12, 13, 14, 15, 16]``. 13 | frame_data_type: Data type, either ``"rgb"``, ``"yuv420"``, ``"yuv444"``. 14 | data: The actual RGB or YUV data 15 | """ 16 | 17 | bitdepth: POSSIBLE_BITDEPTH 18 | frame_data_type: FRAME_DATA_TYPE 19 | data: Any #: Union[Tensor, DictTensorYUV] 20 | 21 | # Filled up by the __post_init__() function 22 | # ==================== Not set by the init function ===================== # 23 | #: Height & width of the video :math:`(H, W)` 24 | img_size: Tuple[int, int] = field(init=False) 25 | #: Number of pixels :math:`H \times W` 26 | n_pixels: int = field(init=False) # Height x Width 27 | # ==================== Not set by the init function ===================== # 28 | 29 | def __post_init__(self): 30 | if self.frame_data_type == "yuv420": 31 | self.img_size = self.data.get("y").size()[-2:] 32 | else: 33 | self.img_size = self.data.size()[-2:] 34 | self.n_pixels = self.img_size[0] * self.img_size[1] 35 | 36 | def to_string(self) -> str: 37 | """Pretty string describing the frame data.""" 38 | s = "Frame data information:\n" 39 | s += "-----------------------\n" 40 | s += f"{'Resolution (H, W)':<26}: {self.img_size[0]}, {self.img_size[1]}\n" 41 | s += f"{'Bitdepth':<26}: {self.bitdepth}\n" 42 | s += f"{'Data type':<26}: {self.frame_data_type}" 43 | 44 | return s 45 | -------------------------------------------------------------------------------- /docs/source/results/image/decoding_complexity.rst: -------------------------------------------------------------------------------- 1 | :layout: simple 2 | 3 | Image decoding complexity 4 | ========================= 5 | 6 | As described in the :doc:`decoder configuration <../../image_compression/architecture>` 7 | section, Cool-chic decoder can be made as simple (or complex) as desired. We 8 | present here the performance-complexity continuum obtained through the :ref:`4 9 | provided configurations ` (*VLOP*, *LOP*, *MOP*, *HOP*). We 10 | also add a *MIX* configuration, where we pick the best configuration out of the 11 | 4 available ones for each image. We used the ``slow_100k`` :ref:`encoding preset 12 | `. 13 | 14 | Decoding complexity is measured both in multiplication per decoded pixel and 15 | decoding time, obtained on a single core of an **AMD EPYC 7282 16-Core 16 | Processor**. 17 | 18 | Kodak 19 | ***** 20 | 21 | .. image:: ../../assets/kodak/all_complexity_dec.png 22 | :alt: Kodak rd results 23 | 24 | CLIC20 Pro Valid 25 | **************** 26 | 27 | .. image:: ../../assets/clic20-pro-valid/all_complexity_dec.png 28 | :alt: CLIC20 rd results 29 | 30 | 31 | JVET Class B 32 | ************ 33 | 34 | .. image:: ../../assets/jvet/all_complexity_dec_classB.png 35 | :alt: JVET class B rd results 36 | 37 | JVET Class C 38 | ************ 39 | 40 | .. image:: ../../assets/jvet/all_complexity_dec_classC.png 41 | :alt: JVET class C rd results 42 | 43 | JVET Class D 44 | ************ 45 | 46 | .. image:: ../../assets/jvet/all_complexity_dec_classD.png 47 | :alt: JVET class D rd results 48 | 49 | JVET Class E 50 | ************ 51 | 52 | .. image:: ../../assets/jvet/all_complexity_dec_classE.png 53 | :alt: JVET class E rd results 54 | 55 | JVET Class F 56 | ************ 57 | 58 | .. image:: ../../assets/jvet/all_complexity_dec_classF.png 59 | :alt: JVET class F rd results 60 | 61 | JVET All Classes 62 | **************** 63 | 64 | .. image:: ../../assets/jvet/all_complexity_dec_classBCDEF.png 65 | :alt: JVET class BCDEF rd results 66 | 67 | 68 | -------------------------------------------------------------------------------- /toolbox/toolbox/identify.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 5 | # SPDX-License-Identifier: BSD 3-Clause "New" 6 | # 7 | # This software is distributed under the BSD-3-Clause license. 8 | # 9 | # Authors: see CONTRIBUTORS.md 10 | 11 | import argparse 12 | import os 13 | from dataclasses import fields 14 | from typing import Any, Dict 15 | 16 | from common.cliprint import dict_to_str 17 | from common.io.image import get_bitdepth_image, is_image, read_image 18 | from common.io.yuv import get_yuv_info 19 | 20 | 21 | def identify_fn(file_path: str) -> Dict[str, Any]: 22 | info = {} 23 | if is_image(file_path): 24 | height, width, _ = read_image(file_path).shape 25 | 26 | # Order here must match the order of the (first) attributes 27 | # of the YUVDescriptor dataclass so that identify returns 28 | # identically ordered results for yuv and png files 29 | info["width"] = width 30 | info["height"] = height 31 | info["n_frames"] = 1 32 | info["bitdepth"] = get_bitdepth_image(file_path) 33 | 34 | # yuv 35 | else: 36 | # Put everything from yuv info into info, except color space 37 | yuv_info = get_yuv_info(file_path) 38 | for f in fields(yuv_info): 39 | if f.name == "colorspace": 40 | pass 41 | info[f.name] = getattr(yuv_info, f.name) 42 | 43 | return info 44 | 45 | 46 | if __name__ == "__main__": 47 | parser = argparse.ArgumentParser() 48 | parser.add_argument( 49 | "-i", "--input", help="Path of the image to identify", type=str, required=True 50 | ) 51 | 52 | parser.add_argument( 53 | "--noheader", help="add column names to results", action="store_true" 54 | ) 55 | args = parser.parse_args() 56 | 57 | assert os.path.exists(args.input), f"Can not found a file named {args.input}" 58 | 59 | info = identify_fn(args.input) 60 | print(dict_to_str(info, noheader=args.noheader)) 61 | -------------------------------------------------------------------------------- /coolchic/cpp/warp_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | #include 11 | #include // timing. 12 | #include 13 | 14 | #include "common.h" 15 | #include "frame-memory.h" 16 | 17 | extern float time_warp_seconds; 18 | extern float time_warp_coeffgen_seconds; 19 | extern float time_warp_coeffget_seconds; 20 | 21 | inline int get_limited_l(int v_start_x, int x_idx) 22 | { 23 | if (x_idx < v_start_x) 24 | x_idx = v_start_x; 25 | return x_idx; 26 | } 27 | 28 | inline int get_limited_r(int v_limit_x, int x_idx) 29 | { 30 | if (x_idx >= v_limit_x-1) 31 | x_idx = v_limit_x-1; 32 | return x_idx; 33 | } 34 | 35 | inline int get_limited(int v_start_x, int v_limit_x, int x_idx) 36 | { 37 | x_idx = get_limited_l(v_start_x, x_idx); 38 | x_idx = get_limited_r(v_limit_x, x_idx); 39 | return x_idx; 40 | } 41 | 42 | // !!! global coeff storage for now. 43 | extern int g_coeff_table_motion_q_shift; 44 | extern int g_coeff_table_ntaps; 45 | extern float *g_coeff_table; // index with [quantval * ntaps]. 46 | 47 | template 48 | void generate_coeffs(int motion_q_shift); 49 | 50 | template 51 | inline P *get_coeffs(int motion_qsteps) 52 | { 53 | return &g_coeff_table[motion_qsteps*NTAPS]; 54 | } 55 | 56 | // return basex and tx (integers) from a float px. 57 | template 58 | inline void get_motion_info(P px, int motion_q_shift, int32_t &basex, int32_t &tx) 59 | { 60 | basex = (int32_t)rintf(px*(1<>= motion_q_shift; 67 | basex = -basex; 68 | } 69 | else 70 | { 71 | basex >>= motion_q_shift; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /toolbox/toolbox/common/io/png.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 2 | # SPDX-License-Identifier: BSD 3-Clause "New" 3 | # 4 | # This software is distributed under the BSD-3-Clause license. 5 | # 6 | # Authors: see CONTRIBUTORS.md 7 | 8 | import numpy as np 9 | from PIL import Image 10 | 11 | 12 | def read_png(file_path: str) -> np.ndarray: 13 | """Read a PNG file and return a numpy array describing it. 14 | The output shape is [H, W, 3] with values in [0., 1.]. 15 | 16 | Args: 17 | file_path (str): Path of the file to load. 18 | 19 | Returns: 20 | np.ndarray: Loaded data as a numpy array, shape is [H, W, 3] and 21 | values are in [0., 1.]. 22 | """ 23 | im = np.array(Image.open(file_path)) 24 | 25 | # Remove alpha channel if any, cast to float 32 and divide by 255 26 | # so that the value are in [0., 1] 27 | im = im[:, :, :3].astype(np.float32) / 255.0 28 | 29 | return im 30 | 31 | 32 | def write_png(data: np.ndarray, file_path: str) -> None: 33 | """Write a numpy array as a PNG file. The numpy array must be 34 | in [0., 1.] with a shape of [H, W, 3]. 35 | 36 | Args: 37 | data (np.ndarray): Numpy array to store in a png file. Values are in 38 | [0., 1.] and shape is [H, W, 3] 39 | file_path (str): Path where the data are stored 40 | """ 41 | assert len(data.shape) == 3 and data.shape[-1] == 3, ( 42 | f"Data shape must be [H, W, 3], found {data.shape}" 43 | ) 44 | 45 | # Recast the PNG to integer with 256 levels 46 | data = np.clip(data, 0.0, 1.0) 47 | data = np.round(data * 255).astype(np.uint8) 48 | 49 | assert data.min() >= 0 and data.max() <= 255, ( 50 | "Data should be in [0., 255.] prior to be saved into PNG file. \n" 51 | f"Found data.min() = {data.min()} and data.max() = {data.max()}." 52 | ) 53 | 54 | im = Image.fromarray(data) 55 | im.save(file_path) 56 | 57 | 58 | def is_png(file_path: str) -> bool: 59 | """Return True if the file is a PNG file, ending with 60 | ".png" or ".PNG". 61 | 62 | Args: 63 | file_path (str): File to be checked 64 | 65 | Returns: 66 | bool: True if file is a png file 67 | """ 68 | 69 | return file_path.endswith(".png") or file_path.endswith(".PNG") 70 | -------------------------------------------------------------------------------- /coolchic/enc/nnquant/quantstep.py: -------------------------------------------------------------------------------- 1 | # Software Name: Cool-Chic 2 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 3 | # SPDX-License-Identifier: BSD 3-Clause "New" 4 | # 5 | # This software is distributed under the BSD-3-Clause license. 6 | # 7 | # Authors: see CONTRIBUTORS.md 8 | 9 | 10 | """All possible quantization steps for each module of a CoolchicEncoder""" 11 | 12 | from typing import Optional 13 | 14 | from enc.component.types import DescriptorNN 15 | import torch 16 | 17 | # Shifts for ARM, record the shift. 18 | POSSIBLE_Q_STEP_SHIFT = { 19 | "arm": { 20 | "weight": torch.linspace(-8, 0, 9, device="cpu"), 21 | "bias": torch.linspace(-16, 0, 17, device="cpu"), 22 | }, 23 | } 24 | 25 | POSSIBLE_Q_STEP = { 26 | "arm": { 27 | "weight": 2.0 ** POSSIBLE_Q_STEP_SHIFT["arm"]["weight"], 28 | "bias": 2.0 ** POSSIBLE_Q_STEP_SHIFT["arm"]["bias"], 29 | }, 30 | "upsampling": { 31 | "weight": 2.0 ** torch.linspace(-12, 0, 13, device="cpu"), 32 | "bias": 2.0 ** torch.tensor([0.0]), 33 | }, 34 | "synthesis": { 35 | "weight": 2.0 ** torch.linspace(-12, 0, 13, device="cpu"), 36 | "bias": 2.0 ** torch.linspace(-24, 0, 25, device="cpu"), 37 | }, 38 | } 39 | 40 | 41 | def get_q_step_from_parameter_name( 42 | parameter_name: str, q_step: DescriptorNN 43 | ) -> Optional[float]: 44 | """Return the specific quantization step from q_step (a dictionary 45 | with several quantization steps). The specific quantization step is 46 | selected through the parameter name. 47 | 48 | Args: 49 | parameter_name (str): Name of the parameter in the state dict. 50 | q_step (DescriptorNN): Dictionary gathering several quantization 51 | steps. E.g. one quantization step for the weights and one for 52 | the biases. 53 | 54 | Returns: 55 | Optional[float]: The quantization step associated to the parameter. 56 | Return None if nothing is found. 57 | """ 58 | if ".weight" in parameter_name: 59 | current_q_step = q_step.get("weight") 60 | elif ".bias" in parameter_name: 61 | current_q_step = q_step.get("bias") 62 | else: 63 | print( 64 | 'Parameter name should include ".weight" or ".bias" ' 65 | f"Found: {parameter_name}" 66 | ) 67 | current_q_step = None 68 | 69 | return current_q_step 70 | -------------------------------------------------------------------------------- /coolchic/cpp/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | 11 | #if !defined(_COMMON_) 12 | 13 | #define _COMMON_ 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // !!! only use float for current video code. 21 | #define UPS_INT_FLOAT float // float or int32_t, if float, SYN_INT_FLOAT must be float 22 | #define SYN_INT_FLOAT float // float or int32_t 23 | 24 | int const ARM_MAX_N_FEATURES = 32; 25 | 26 | // 64-alignment for possible avx512 use 27 | #define ALIGNTO 64 28 | #define ALIGN(val) ((val+ALIGNTO-1)/ALIGNTO*ALIGNTO) 29 | 30 | #define ARM_PRECISION 8 31 | #define ARM_SCALE (1< 44 | struct buffer 45 | { 46 | buffer(): data(NULL), n(0) {} 47 | ~buffer() { unuse(); } 48 | P *data; 49 | int n; 50 | P *update_to(int new_n) { if (new_n <= n) return data; 51 | unuse(); 52 | n = new_n; 53 | data = (P *)aligned_alloc(ALIGNTO, ALIGN(n*sizeof(data[0]))); 54 | if (data == NULL) 55 | { 56 | printf("Cannot allocate weight/bias data: %d elements", new_n); 57 | exit(1); 58 | } 59 | return data; 60 | } 61 | private: 62 | void unuse() { if (data != NULL) {free(data); data = NULL;} } 63 | }; 64 | using weights_biases = buffer; 65 | using weights_biases_ups = buffer; 66 | using weights_biases_syn = buffer; 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /toolbox/toolbox/yuv_extract.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 5 | # SPDX-License-Identifier: BSD 3-Clause "New" 6 | # 7 | # This software is distributed under the BSD-3-Clause license. 8 | # 9 | # Authors: see CONTRIBUTORS.md 10 | 11 | 12 | """Extract the i-th frame of a YUV file and save it somewhere""" 13 | 14 | import argparse 15 | import os 16 | import subprocess 17 | 18 | from common.io.yuv import get_yuv_info 19 | 20 | 21 | def extract_frame( 22 | input_path: str, output_path: str, frame_idx: int, verbosity: int 23 | ) -> None: 24 | """Wrapper around the dd command to extract the i-th frame of a YUV file 25 | and save it somewhere. 26 | 27 | Args: 28 | input_path (str): Path of the input video 29 | output_path (str): Path of the output extracted frame 30 | frame_idx (int): Index of the frame to be extracted. 0 is the first 31 | verbosity (int): Set to > 0 to print more stuff 32 | """ 33 | assert os.path.isfile(input_path), f"File {input_path} not found!" 34 | assert input_path != output_path, ( 35 | f"Input and output files must be different. Found {input_path} for both" 36 | ) 37 | 38 | yuv_info = get_yuv_info(input_path) 39 | 40 | n_pixel_per_frame = yuv_info.width * yuv_info.height + 2 * ( 41 | yuv_info.width_uv * yuv_info.height_uv 42 | ) 43 | n_bytes_per_frame = ( 44 | n_pixel_per_frame if yuv_info.bitdepth <= 8 else n_pixel_per_frame * 2 45 | ) 46 | 47 | block_size = n_bytes_per_frame 48 | blocks_to_skip = frame_idx 49 | cmd = ( 50 | "dd" 51 | f" if={input_path}" 52 | f" of={output_path}" 53 | f" bs={block_size}" 54 | f" skip={blocks_to_skip}" 55 | f" count=1" 56 | ) 57 | if verbosity == 0: 58 | cmd += " status=none " 59 | 60 | subprocess.call(cmd, shell=True) 61 | 62 | 63 | if __name__ == "__main__": 64 | parser = argparse.ArgumentParser() 65 | parser.add_argument( 66 | "-i", "--input", help="Path of the input video", type=str, required=True 67 | ) 68 | parser.add_argument( 69 | "-o", 70 | "--output", 71 | help="Path of the output extracted frame", 72 | type=str, 73 | required=True, 74 | ) 75 | parser.add_argument( 76 | "--idx", help="Index of the frame to be extracted", type=int, required=True 77 | ) 78 | parser.add_argument( 79 | "-v", "--verbosity", help="verbosity level", type=int, default=0 80 | ) 81 | args = parser.parse_args() 82 | 83 | extract_frame(args.input, args.output, args.idx, args.verbosity) 84 | -------------------------------------------------------------------------------- /results/v4.0/video-ra-jvet-c.tsv: -------------------------------------------------------------------------------- 1 | seq_name lmbda rate_bpp n_pixels h w n_frames psnr_db dec_time_arm_sec dec_time_ups_sec dec_time_syn_sec dec_time_blend_sec dec_time_warp_sec dec_time_bpred_sec dec_time_all_sec 2 | C-RaceHorses_832x480_30p_yuv420_8b 0.002 0.05884515224358974 119808000 480 832 300 30.314141397855426 1.02868 0.988748 10.2997 0.0 2.6482 0.459929 16.5634 3 | C-BasketballDrill_832x480_50p_yuv420_8b 0.002 0.036399198717948715 199680000 480 832 500 32.954903378339466 0.836287 1.62561 16.3736 0.0 4.24875 0.857586 25.5332 4 | C-PartyScene_832x480_50p_yuv420_8b 0.002 0.046091746794871796 199680000 480 832 500 28.863891423232516 1.3224 1.36184 15.7993 0.0 4.03887 0.867148 25.1004 5 | C-BQMall_832x480_60p_yuv420_8b 0.002 0.03576639289529915 239616000 480 832 600 32.453910275964304 1.21582 2.12203 21.5356 0.0 5.31851 1.19237 33.8693 6 | C-RaceHorses_832x480_30p_yuv420_8b 0.0007 0.10964022435897436 119808000 480 832 300 32.478184987999875 1.72227 1.15736 10.1125 0.0 2.66052 0.499276 17.152 7 | C-BasketballDrill_832x480_50p_yuv420_8b 0.0007 0.0561573717948718 199680000 480 832 500 34.96591038897103 1.33751 1.82925 16.5249 0.0 4.1615 0.905337 26.6066 8 | C-PartyScene_832x480_50p_yuv420_8b 0.0007 0.08512355769230769 199680000 480 832 500 30.89149372032379 2.2797 1.8528 16.7314 0.0 4.15188 0.9159 27.6093 9 | C-BQMall_832x480_60p_yuv420_8b 0.0007 0.056931690705128206 239616000 480 832 600 34.69594621288665 1.94533 2.03782 20.5213 0.0 5.09779 1.11439 33.0017 10 | C-RaceHorses_832x480_30p_yuv420_8b 0.0002 0.23001903044871794 119808000 480 832 300 35.26008339212598 2.93601 1.26309 10.3583 0.0 2.72387 0.530817 18.8709 11 | C-BasketballDrill_832x480_50p_yuv420_8b 0.0002 0.10426963141025641 199680000 480 832 500 37.59269653688078 2.50983 1.90403 16.4826 0.0 4.16342 0.914645 27.9159 12 | C-PartyScene_832x480_50p_yuv420_8b 0.0002 0.18924270833333334 199680000 480 832 500 33.73627172172439 4.18843 1.76506 16.2386 0.0 4.08843 0.848089 29.2119 13 | C-BQMall_832x480_60p_yuv420_8b 0.0002 0.10532124732905983 239616000 480 832 600 37.29285570918043 3.31778 2.26157 20.7503 0.0 5.15335 1.16723 34.9125 14 | C-RaceHorses_832x480_30p_yuv420_8b 6e-05 0.47115264423076925 119808000 480 832 300 38.141881815856436 4.48992 1.25121 10.1524 0.0 2.65533 0.526228 20.1072 15 | C-BasketballDrill_832x480_50p_yuv420_8b 6e-05 0.2035773237179487 199680000 480 832 500 40.25873658774282 3.92968 1.90294 16.156 0.0 4.1217 0.841357 29.161 16 | C-PartyScene_832x480_50p_yuv420_8b 6e-05 0.4074038862179487 199680000 480 832 500 37.0040535353283 7.00938 1.92938 16.5807 0.0 4.12709 0.90244 32.4164 17 | C-BQMall_832x480_60p_yuv420_8b 6e-05 0.2042125734508547 239616000 480 832 600 39.73443797048596 7.0165 2.47822 22.7123 0.0 5.57271 1.14353 41.9566 18 | -------------------------------------------------------------------------------- /coolchic/cpp/cc-contexts.h: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | // some numbers and indices related to mu and sig quantization. 11 | int const N_MUQ = 16; // number of mu offsets. 12 | int const N_SIGQ = 50; // number of sig values. now 50, so multiple of 10 13 | int const ZERO_MU = N_MUQ/2; 14 | 15 | int const SIG_LOG_MIN = -1; // this min is IN the set. 16 | int const SIG_LOG_MAX_EXCL = 9; // this max is NOT in the set. 17 | 18 | int const PROBA_50_STATE = (2*32+1); // generate a BinProbModel_Std with 50% probability. 19 | 20 | inline 21 | void get_val_mu_indicies(int val_mu, int val_log_sig, 22 | int &r_val_mu_rounded, int &r_val_mu_index, int &r_val_log_sig_index) 23 | { 24 | int val_mu_rounded = val_mu; 25 | val_mu_rounded = (val_mu_rounded >= 0) ? (val_mu_rounded+ARM_SCALE/2)>>ARM_PRECISION<>ARM_PRECISION<= 0 ? ((val_mu_index+ARM_SCALE/2)>>ARM_PRECISION) : -((-val_mu_index+ARM_SCALE/2)>>ARM_PRECISION); 30 | val_mu_index += N_MUQ/2; 31 | 32 | // no longer a table. 33 | int val_log_sig_index; 34 | val_log_sig -= SIG_LOG_MIN*ARM_SCALE; 35 | if (val_log_sig < 0) 36 | val_log_sig_index = 0; 37 | else 38 | { 39 | val_log_sig_index = val_log_sig*(N_SIGQ/(SIG_LOG_MAX_EXCL-SIG_LOG_MIN))+ARM_SCALE/2; 40 | val_log_sig_index >>= ARM_PRECISION; 41 | if (val_log_sig_index >= N_SIGQ) 42 | val_log_sig_index = N_SIGQ-1; 43 | } 44 | 45 | r_val_mu_rounded = val_mu_rounded>>ARM_PRECISION; 46 | r_val_mu_index = val_mu_index; 47 | r_val_log_sig_index = val_log_sig_index; 48 | } 49 | 50 | 51 | // contexts 17 mus, 50 sigmas 52 | // Context numbers for gtx and ppos for a given mu and sigma. 53 | class MuSigGTs 54 | { 55 | public: 56 | MuSigGTs(int gt0, int gt1, int gt2, int gt3, int ppos) 57 | { 58 | m_gt0 = BinProbModel_Std(gt0); 59 | m_gt1 = BinProbModel_Std(gt1); 60 | m_gt2 = BinProbModel_Std(gt2); 61 | m_gt3 = BinProbModel_Std(gt3); 62 | m_ppos = BinProbModel_Std(ppos); 63 | } 64 | ~MuSigGTs() {} 65 | public: 66 | BinProbModel_Std m_gt0; 67 | BinProbModel_Std m_gt1; 68 | BinProbModel_Std m_gt2; 69 | BinProbModel_Std m_gt3; 70 | BinProbModel_Std m_ppos; 71 | }; 72 | 73 | extern MuSigGTs g_contexts[N_MUQ+1][N_SIGQ]; 74 | -------------------------------------------------------------------------------- /coolchic/cpp/syn_cpu.h: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | 11 | //void custom_conv_ks1_inX_outX(int KS, int32_t *kw, int32_t *kb, int h_in, int w_in, int stride_in, int plane_stride_in, int residue_origin_offset, int N_IN, int32_t *in, int N_OUT, int32_t *out, int residue, int relu); 12 | //void custom_conv_ksX_inX_outX(int KS, int32_t *kw, int32_t *kb, int h_in, int w_in, int stride_in, int plane_stride_in, int residue_origin_offset, int N_IN, int32_t *in, int N_OUT, int32_t *out, int residue, int relu); 13 | //void custom_conv_ks1_inX_hiddenX_outX(int KS, int32_t *kw7_40, int32_t *kb40, int32_t *kw40_3, int32_t *kb3, int h_in, int w_in, int pad_in, int plane_stride_in, int N_IN, int N_HIDDEN, int32_t *in, int N_OUT, int32_t *out); 14 | 15 | //void custom_conv_ks3_inX_outX_lb(int KS, int32_t *kw, int32_t *kb, int h_in, int w_in, int stride_in, int plane_stride_in, int residue_origin_offset, int N_IN, int32_t *in, int N_OUT, int32_t *out, int32_t *line_buffer, int residue, int relu); 16 | 17 | //void syn_blend1(int h_in, int w_in, int stride_in, int plane_stride_in, int N_INOUT, int32_t *in, int32_t blend_val_in, int32_t *out); 18 | //void syn_blend2(int h_in, int w_in, int stride_in, int plane_stride_in, int N_INOUT, int32_t *in, int32_t blend_val_in, int32_t *out, int32_t blend_val_out); 19 | 20 | template 21 | void custom_conv_ks1_inX_outX(int KS, P *kw, P *kb, int h_in, int w_in, int stride_in, int plane_stride_in, int residue_origin_offset, int N_IN, P *in, int N_OUT, P *out, int residue, int relu); 22 | template 23 | void custom_conv_ksX_inX_outX(int KS, P *kw, P *kb, int h_in, int w_in, int stride_in, int plane_stride_in, int residue_origin_offset, int N_IN, P *in, int N_OUT, P *out, int residue, int relu); 24 | 25 | template 26 | void custom_conv_ks1_inX_hiddenX_outX(int KS, P *kw7_40, P *kb40, P *kw40_3, P *kb3, int h_in, int w_in, int pad_in, int plane_stride_in, int N_IN, int N_HIDDEN, P *in, int N_OUT, P *out); 27 | 28 | template 29 | void custom_conv_ks3_inX_outX_lb(int KS, P *kw, P *kb, int h_in, int w_in, int stride_in, int plane_stride_in, int residue_origin_offset, int N_IN, P *in, int N_OUT, P *out, P *line_buffer, int residue, int relu); 30 | template 31 | void syn_blend1(int h_in, int w_in, int stride_in, int plane_stride_in, int N_INOUT, P *in, int32_t blend_val_in, P *out); 32 | template 33 | void syn_blend2(int h_in, int w_in, int stride_in, int plane_stride_in, int N_INOUT, P *in, int32_t blend_val_in, P *out, int32_t blend_val_out); 34 | -------------------------------------------------------------------------------- /coolchic/dec/nn.py: -------------------------------------------------------------------------------- 1 | # Software Name: Cool-Chic 2 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 3 | # SPDX-License-Identifier: BSD 3-Clause "New" 4 | # 5 | # This software is distributed under the BSD-3-Clause license. 6 | # 7 | # Authors: see CONTRIBUTORS.md 8 | 9 | 10 | from enc.component.types import DescriptorNN 11 | import torch 12 | import torch.nn as nn 13 | 14 | from CCLIB.ccencapi import cc_decode_wb 15 | 16 | 17 | def decode_network( 18 | empty_module: nn.Module, 19 | bitstream_path: DescriptorNN, 20 | q_step_nn: DescriptorNN, 21 | scale_nn: DescriptorNN, 22 | ac_max_val: int, 23 | ) -> nn.Module: 24 | """Decode a neural network from a bitstream. The idea is to iterate 25 | on all the parameters of , filling it with values read 26 | from the bitstream. 27 | 28 | Args: 29 | empty_module (nn.Module): An empty (i.e. randomly initialized) instance 30 | of the network to load. 31 | bitstream_path (str): Weight and bias will be found at 32 | _weight and _arm 33 | q_step_nn (DescriptorNN): Describe the quantization steps used 34 | for the weight and bias of the network. 35 | scale_nn (DescriptorNN): Describe the scale parameters used 36 | for entropy coding of the weight and bias of the network. 37 | ac_max_val (int): Data are in [-ac_max_val, ac_max_val - 1] 38 | 39 | Returns: 40 | nn.Module: The decoded module 41 | """ 42 | have_bias = bitstream_path.bias != "" 43 | 44 | # Instantiate two range coder objects to decode simultaneously weight and bias 45 | bac_ctx_weight = cc_decode_wb(bitstream_path.weight) 46 | if have_bias: 47 | bac_ctx_bias = cc_decode_wb(bitstream_path.bias) 48 | 49 | loaded_param = {} 50 | for k, v in empty_module.named_parameters(): 51 | if "weight" in k: 52 | cur_q_step = q_step_nn.weight 53 | cur_param = bac_ctx_weight.decode_wb_continue(len(v.flatten()), scale_nn.weight) 54 | elif "bias" in k and have_bias: 55 | cur_q_step = q_step_nn.bias 56 | cur_param = bac_ctx_bias.decode_wb_continue(len(v.flatten()), scale_nn.bias) 57 | else: 58 | # Ignore network parameters whose name does not end with '.w', '.b', '.weight', '.bias' 59 | continue 60 | 61 | # Don't forget inverse quantization! 62 | loaded_param[k] = torch.tensor(cur_param).reshape_as(v) * cur_q_step 63 | 64 | # empty_module.load_state_dict(loaded_param) 65 | if "arm" in bitstream_path.weight: 66 | empty_module.set_param_from_float(loaded_param) 67 | else: 68 | empty_module.load_state_dict(loaded_param, strict = have_bias) 69 | return empty_module 70 | -------------------------------------------------------------------------------- /coolchic/cpp/arm_avx2.h: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | void custom_conv_11_int32_avx2_8_X_X(weights_biases *kwtX_n_n, weights_biases *kbX_n, // kwtX_n_n[n_hidden_layers] -- kernel weights, transposed. 11 | weights_biases *kwOUT_n_2, weights_biases *kbOUT_2, // _n_2, weights not transposed. 12 | int32_t *context_indicies, int32_t n_contexts_param, int32_t n_hidden_layers_param, 13 | int32_t *src, 14 | int src_h, int src_w, int src_pad, 15 | BACContext &bac_context 16 | ); 17 | void custom_conv_11_int32_avx2_16_X_X(weights_biases *kwtX_n_n, weights_biases *kbX_n, // kwtX_n_n[n_hidden_layers] -- kernel weights, transposed. 18 | weights_biases *kwOUT_n_2, weights_biases *kbOUT_2, // _n_2, weights not transposed. 19 | int32_t *context_indicies, int32_t n_contexts_param, int32_t n_hidden_layers_param, 20 | int32_t *src, 21 | int src_h, int src_w, int src_pad, 22 | BACContext &bac_context 23 | ); 24 | void custom_conv_11_int32_avx2_24_X_X(weights_biases *kwtX_n_n, weights_biases *kbX_n, // kwtX_n_n[n_hidden_layers] -- kernel weights, transposed. 25 | weights_biases *kwOUT_n_2, weights_biases *kbOUT_2, // _n_2, weights not transposed. 26 | int32_t *context_indicies, int32_t n_contexts_param, int32_t n_hidden_layers_param, 27 | int32_t *src, 28 | int src_h, int src_w, int src_pad, 29 | BACContext &bac_context 30 | ); 31 | void custom_conv_11_int32_avx2_32_X_X(weights_biases *kwtX_n_n, weights_biases *kbX_n, // kwtX_n_n[n_hidden_layers] -- kernel weights, transposed. 32 | weights_biases *kwOUT_n_2, weights_biases *kbOUT_2, // _n_2, weights not transposed. 33 | int32_t *context_indicies, int32_t n_contexts_param, int32_t n_hidden_layers_param, 34 | int32_t *src, 35 | int src_h, int src_w, int src_pad, 36 | BACContext &bac_context 37 | ); 38 | -------------------------------------------------------------------------------- /docs/source/video_compression/architecture.rst: -------------------------------------------------------------------------------- 1 | Decoder configuration 2 | ===================== 3 | 4 | .. image:: ../assets/frame-decoding-2.png 5 | :alt: Cool-chic inter-frame decoder overview 6 | 7 | Inter frames (P or B) decoders involves two Cool-chic decoders, one for the 8 | residue and one for the motion while intra frames only requires a residue 9 | decoder. Each Cool-chic decoder has the same architecture as the one described 10 | in the :ref:`image coding section. ` 11 | 12 | Since the residue and motion Cool-chic decoders have the same design, they are 13 | parameters through similar arguments. For instance ``--arm_residue`` sets up the 14 | the ARM architecture for the residue decoder, while ``--arm_motion`` achieves 15 | the same thing for the motion decoder. 16 | 17 | Similarly, it is possible to provide a decoder configuration file for the motion 18 | Cool-chic decoder through the ``--dec_cfg_motion`` arguments. Example 19 | configuration files are listed in ``cfg/dec/motion/``. 20 | 21 | Motion compensation options 22 | """"""""""""""""""""""""""" 23 | 24 | Motion compensation requires to interpolate in between pixels e.g., to achieve a 25 | shift of 7.25 pixels. To do so, an interpolation filter is used. The size of the 26 | interpolation filter is parameterized by ``--warp_filter_size``. See paper `Efficient Sub-pixel Motion 27 | Compensation in Learned Video Codecs, Ladune et al 28 | `_ for more details. 29 | 30 | The type of interpolation performed is derived from the filter size. Note that 31 | ``--warp_filter_size`` must be even 32 | 33 | .. list-table:: Motion compensation interpolation. 34 | :widths: 30 30 35 | :header-rows: 1 36 | 37 | * - ``warp_filter_size`` 38 | - Type 39 | * - 2 40 | - Bilinear 41 | * - 4 42 | - Bicubic 43 | * - 6 or above 44 | - Sinc-based 45 | 46 | Motion fields downsampling 47 | """""""""""""""""""""""""" 48 | 49 | To obtain uniform motion on a block of :math:`B \times B` pixels, we rely on 50 | ``--n_ft_per_res_motion``. As explained :ref:`here `, having 51 | the first :math:`N` latents of the motion Cool-chic with no feature leads to a 52 | decoding of a motion fields with motion values common to blocks of :math:`2^N 53 | \times 2^N` pixels. 54 | 55 | .. code-block:: 56 | 57 | # Each motion vector is common for a block of 8x8 pixels. 58 | --n_ft_per_res_motion=0,0,0,1,1 59 | 60 | Frame-wise decoder configuration 61 | """""""""""""""""""""""""""""""" 62 | 63 | In a hierarchical coding structure, not all frames are equally important. As 64 | such, it is often interesting to use lighter architectures for not-so-important 65 | frames. The :ref:`video coding example script ` 66 | provides an example of frame-wise decoder configuration automatically generated. 67 | -------------------------------------------------------------------------------- /coolchic/decode.py: -------------------------------------------------------------------------------- 1 | # Software Name: Cool-Chic 2 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 3 | # SPDX-License-Identifier: BSD 3-Clause "New" 4 | # 5 | # This software is distributed under the BSD-3-Clause license. 6 | # 7 | # Authors: see CONTRIBUTORS.md 8 | 9 | import argparse 10 | import sys 11 | 12 | from CCLIB.ccdecapi_cpu import cc_decode_cpu 13 | 14 | """ 15 | C++ decode interface 16 | """ 17 | 18 | if __name__ == "__main__": 19 | # =========================== Parse arguments =========================== # 20 | parser = argparse.ArgumentParser() 21 | parser.add_argument( 22 | "--input", "-i", type=str, default="./bitstream.cool", help="Bitstream path." 23 | ) 24 | parser.add_argument("--output", "-o", default="", help="output ppm (rgb) or yuv") 25 | # parser.add_argument("--avx2", action="store_true", help="Use AVX2. Some operations might be unavailable") 26 | parser.add_argument( 27 | "--verbosity", type=int, default=0, 28 | help="" 29 | "0 does not output anything ; " 30 | "1 prints the runtime of each step ;" 31 | "2 is for debug." 32 | ) 33 | parser.add_argument( 34 | "--output_chroma_format", 35 | type=int, 36 | default=0, 37 | help= 38 | "Use 0 to infer this from the bitstream header. " 39 | " " 40 | "Otherwise, specify '420' or '444' to change the chroma sampling for the " 41 | "YUV output. " 42 | " " 43 | " Useless for RGB." 44 | ) 45 | parser.add_argument( 46 | "--output_bitdepth", 47 | type=int, 48 | default=0, 49 | help= 50 | "Use 0 to infer this from the bitstream header. " 51 | " " 52 | "Otherwise, specify an integer in [8, 16] to set the output bitdepth." 53 | ) 54 | parser.add_argument( 55 | "--motion_accuracy", 56 | type=int, 57 | default=64, 58 | help="motion accuracy 1/n; n defaults to 64." 59 | ) 60 | args = parser.parse_args() 61 | # =========================== Parse arguments =========================== # 62 | 63 | use_avx2 = False # args.avx2 64 | 65 | if use_avx2: 66 | from CCLIB.ccdecapi_avx2 import cc_decode_avx2 67 | 68 | if args.verbosity >= 2: 69 | print("Using AVX2 instructions for faster decoding") 70 | cc_decode_avx2( 71 | args.input, 72 | args.output, 73 | args.output_bitdepth, 74 | args.output_chroma_format, 75 | args.motion_accuracy, 76 | args.verbosity, 77 | ) 78 | else: 79 | cc_decode_cpu( 80 | args.input, 81 | args.output, 82 | args.output_bitdepth, 83 | args.output_chroma_format, 84 | args.motion_accuracy, 85 | args.verbosity, 86 | ) 87 | -------------------------------------------------------------------------------- /docs/source/getting_started/example.rst: -------------------------------------------------------------------------------- 1 | Example 2 | ======= 3 | 4 | Cool-chic encodes each video frames successively through the 5 | ``coolchic/encode.py`` script. An image is simply a video with a single frame. 6 | 7 | 8 | Encoding an image into a .cool bitstream 9 | """""""""""""""""""""""""""""""""""""""" 10 | 11 | Encoding an image or a video frame with CoolChic requires to specify 12 | 13 | * The input image path ``-i`` and output bitstream path ``-o`` 14 | 15 | * A working directory ``--workdir`` where logs are written. 16 | 17 | * The encoder configuration ``--enc_cfg`` for the training options. 18 | 19 | * The decoder configuration ``--dec_cfg_residue`` for the neural networks architecture. 20 | 21 | * The rate constraint ``--lmbda`` setting the compressed file size. 22 | 23 | .. code:: bash 24 | 25 | (venv) ~/Cool-Chic$ python coolchic/encode.py \ 26 | -i=image.png \ 27 | -o=./bitstream.cool \ 28 | --workdir=./dummy_workdir \ 29 | --enc_cfg=cfg/enc/intra/fast_10k.cfg \ 30 | --dec_cfg_residue=cfg/dec/intra/hop.cfg \ 31 | --lmbda=0.001 # Typical range is 1e-2 (low rate) to 1e-4 (high rate) 32 | 33 | More details on encoding images with Cool-chic is available in the :doc:`encoder documentation <./../image_compression/overview>`. 34 | 35 | .. _video_coding_example: 36 | 37 | Encoding a video into a .cool bitstream 38 | """"""""""""""""""""""""""""""""""""""" 39 | 40 | Encoding a video requires to encode successively each video frames through the 41 | ``coolchic/encode.py`` script. We provide a ``samples/encode.py`` script 42 | allowing to easily do video encoding. 43 | 44 | .. code:: bash 45 | 46 | # Encode the first 33 frames of a video, with an intra at the beginning (0) 47 | # and at the end (-1) 48 | (venv) ~/Cool-Chic$ python samples/encode.py \ 49 | -i myTestVideo_1920x1080_24p_yuv420_8b.yuv \ 50 | -o myTestVideo_1920x1080_24p_yuv420_8b.cool \ 51 | --workdir=./dummy_workdir \ 52 | --lmbda=0.001 \ 53 | --n_frames=33 \ 54 | --intra_pos=0,-1 55 | 56 | 57 | .. _decoding_example: 58 | 59 | Decoding a .cool bitstream 60 | """""""""""""""""""""""""" 61 | 62 | 63 | Decoding an image or a video with CoolChic requires to specify the input and output paths. 64 | We provide a few already encoded bitstreams, ready to be decoded in ``samples/bitstreams/``. 65 | 66 | * The input bitstream path ``-i`` and the decoded image path ``-o`` 67 | 68 | .. code:: bash 69 | 70 | (venv) ~/Cool-Chic$ python coolchic/decode.py \ 71 | -i=samples/bitstream/kodim14.cool \ 72 | -o=decoded-kodim14.ppm \ 73 | --verbosity=1 74 | 75 | Note that Cool-Chic outputs either `PPM 76 | `_ or `YUV 77 | `_ files. 78 | 79 | More details on decoding images with Cool-chic is available in the :doc:`decoder documentation <./../image_compression/decoding_images>`. -------------------------------------------------------------------------------- /coolchic/cpp/Contexts.cpp: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2010-2025, ITU/ISO/IEC 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /** \file Contexts.cpp 35 | * \brief Classes providing probability descriptions and contexts (also contains context initialization values) 36 | */ 37 | 38 | #include "Contexts.h" 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | 45 | const uint8_t ProbModelTables::m_RenormTable_32[32] = 46 | { 47 | 6, 5, 4, 4, 48 | 3, 3, 3, 3, 49 | 2, 2, 2, 2, 50 | 2, 2, 2, 2, 51 | 1, 1, 1, 1, 52 | 1, 1, 1, 1, 53 | 1, 1, 1, 1, 54 | 1, 1, 1, 1 55 | }; 56 | 57 | void BinProbModel_Std::init( int qp, int initId ) 58 | { 59 | int slope = (initId >> 3) - 4; 60 | int offset = ((initId & 7) * 18) + 1; 61 | int inistate = ((slope * (qp - 16)) >> 1) + offset; 62 | int state_clip = inistate < 1 ? 1 : inistate > 127 ? 127 : inistate; 63 | const int p1 = (state_clip << 8); 64 | m_state[0] = p1 & MASK_0; 65 | m_state[1] = p1 & MASK_1; 66 | //printf("m0%0x m1%0x,s0%d,s1%d\n", MASK_0, MASK_1, m_state[0], m_state[1]); 67 | } 68 | -------------------------------------------------------------------------------- /docs/source/encoding/overview.rst: -------------------------------------------------------------------------------- 1 | Overview 2 | ======== 3 | 4 | Encoding your own image or video is achieved by using the script ``coolchic/encode.py``. 5 | 6 | .. code:: bash 7 | 8 | (venv) ~/Cool-Chic$ python coolchic/encode.py \ 9 | --input=path_to_my_example \ 10 | --output=bitstream.bin \ 11 | --workdir=./my_temporary_workdir/ \ 12 | --enc_cfg=cfg/enc/fast_10k.cfg \ 13 | --dec_cfg=cfg/dec/mop.cfg \ 14 | --lmbda=0.001 # Typical range is 1e-2 (low rate) to 1e-4 (high rate) 15 | 16 | Unlike the decoding script which only takes input and output arguments, the 17 | encoder has many arguments allowing to tune Cool-chic for your need. 18 | 19 | * :ref:`Encoder configuration ` affects the encoding duration by 20 | changing the training parameters. This is set through the argument 21 | ``--enc_cfg``. Several encoder configuration files are available in ``cfg/enc/``. 22 | 23 | * :ref:`Decoder configuration ` parametrizes the decoder 24 | architecture and complexity. This is set through the argument ``--dec_cfg``. 25 | Several encoder configuration files are available in ``cfg/dec/``. 26 | 27 | Working directory 28 | """"""""""""""""" 29 | 30 | The ``--workdir`` argument is used to specify a folder where all necessary data will be stored. 31 | This includes the encoder logs and the PyTorch model (``workdir/video_encoder.pt``). 32 | 33 | .. attention:: 34 | 35 | If present, the PyTorch model inside workdir ``workdir/video_encoder.pt`` is reloaded 36 | by the ``coolchic/encode.py`` script. In order to encode 37 | a new image using the same workdir, you must first clean out the workdir. 38 | 39 | I/O format 40 | """""""""" 41 | 42 | Cool-chic is able to encode PPM, PNG, YUV420 & YUV 444 files. The naming of YUV files 43 | must comply with the following convention 44 | 45 | .. code:: bash 46 | 47 | --input=_x_p_yuv_b.yuv 48 | 49 | Note that Cool-Chic outputs either `PPM 50 | `_ (and not PNG!) or `YUV 51 | `_ files. 52 | 53 | Rate constraint 54 | """"""""""""""" 55 | 56 | The rate constraint ``--lmbda`` is used to balance the rate and the distortion when encoding an image. 57 | Indeed, Cool-chic parameters are optimized through gradient descent according to the following rate-distortion objective: 58 | 59 | .. math:: 60 | 61 | \mathcal{L} = ||\mathbf{x} - \hat{\mathbf{x}}||^2 + \lambda 62 | (\mathrm{R}(\hat{\mathbf{x}})), \text{ with } 63 | \begin{cases} 64 | \mathbf{x} & \text{the original image}\\ \hat{\mathbf{x}} & 65 | \text{the coded image}\\ \mathrm{R}(\hat{\mathbf{x}}) & 66 | \text{a measure of the rate of } \hat{\mathbf{x}}\\ 67 | \lambda & \text{the rate constraint }\texttt{--lmbda} 68 | \end{cases} 69 | -------------------------------------------------------------------------------- /results/v4.1/video-ra-jvet-c.tsv: -------------------------------------------------------------------------------- 1 | seq_name lmbda rate_bpp n_pixels h w n_frames psnr_db dec_time_arm_sec dec_time_ups_sec dec_time_syn_sec dec_time_blend_sec dec_time_warp_sec dec_time_coeffgen_sec dec_time_coeffget_sec dec_time_bpred_sec dec_time_all_sec 2 | C-RaceHorses_832x480_30p_yuv420_8b 0.002 0.059436965811965815 119808000 480 832 300 30.662995723006482 1.20275 0.504804 6.1664 0.0 13.9564 0.00016425 0.416296 0.407236 22.8907 3 | C-BasketballDrill_832x480_50p_yuv420_8b 0.002 0.03602688301282051 199680000 480 832 500 33.37046990391618 0.895443 0.774212 10.2698 0.0 22.3952 0.000242806 0.848217 0.621407 36.0354 4 | C-PartyScene_832x480_50p_yuv420_8b 0.002 0.046319511217948715 199680000 480 832 500 29.929224659243687 1.53989 0.743249 10.2718 0.0 22.4064 0.000232271 0.84825 0.61343 36.5314 5 | C-BQMall_832x480_60p_yuv420_8b 0.002 0.03528195112179487 239616000 480 832 600 33.02308034836251 1.31292 0.786781 12.3007 0.0 27.2409 0.00027256 1.00008 0.644901 43.5136 6 | C-RaceHorses_832x480_30p_yuv420_8b 0.0007 0.10517007211538462 119808000 480 832 300 32.942035075888484 2.05217 0.526249 6.17086 0.0 13.9407 0.000173286 0.416046 0.393764 23.659 7 | C-BasketballDrill_832x480_50p_yuv420_8b 0.0007 0.05404166666666667 199680000 480 832 500 35.51053015603565 1.51941 0.821255 10.2723 0.0 22.4671 0.000242846 0.84796 0.561785 36.6006 8 | C-PartyScene_832x480_50p_yuv420_8b 0.0007 0.07917616185897436 199680000 480 832 500 32.348688591958926 2.45402 0.802237 10.2728 0.0 22.5106 0.000236491 0.847983 0.554985 37.6576 9 | C-BQMall_832x480_60p_yuv420_8b 0.0007 0.05403462206196581 239616000 480 832 600 35.39295743387568 2.15503 0.853628 12.3079 0.0 27.2729 0.000264626 1.00007 0.786676 44.5879 10 | C-RaceHorses_832x480_30p_yuv420_8b 0.0002 0.20665291132478633 119808000 480 832 300 35.71226960282842 3.45552 0.543122 6.17528 0.0 13.9171 0.000143409 0.416525 0.414825 25.1932 11 | C-BasketballDrill_832x480_50p_yuv420_8b 0.0002 0.09624667467948718 199680000 480 832 500 38.21121219424274 2.91112 0.873021 10.2777 0.0 22.2604 0.000248008 0.848123 0.612045 37.9044 12 | C-PartyScene_832x480_50p_yuv420_8b 0.0002 0.15117123397435897 199680000 480 832 500 35.07017770130965 3.96916 0.862038 10.2859 0.0 22.3928 0.000252748 0.849705 0.64198 39.1355 13 | C-BQMall_832x480_60p_yuv420_8b 0.0002 0.09533510283119657 239616000 480 832 600 38.04301379759292 3.63495 0.931623 12.3077 0.0 27.27 0.000283349 1.00009 0.668986 46.0542 14 | C-RaceHorses_832x480_30p_yuv420_8b 6e-05 0.413386952457265 119808000 480 832 300 38.34404229751128 5.62217 0.565986 6.17496 0.0 14.0331 0.000158326 0.41686 0.455191 27.5665 15 | C-BasketballDrill_832x480_50p_yuv420_8b 6e-05 0.17821766826923077 199680000 480 832 500 40.7899343109404 4.65844 0.9116 10.2798 0.0 22.43 0.00024499 0.848073 0.550657 39.9109 16 | C-PartyScene_832x480_50p_yuv420_8b 6e-05 0.3016506810897436 199680000 480 832 500 37.77995377540279 6.82915 0.899829 10.2883 0.0 22.415 0.000228582 0.847963 0.640715 42.1483 17 | C-BQMall_832x480_60p_yuv420_8b 6e-05 0.1727040264423077 239616000 480 832 600 40.246139689592155 5.68826 1.0231 12.3306 0.0 27.1291 0.00028414 1.00008 0.845136 48.2617 18 | -------------------------------------------------------------------------------- /results/v4.2/video-ra-jvet-c.tsv: -------------------------------------------------------------------------------- 1 | seq_name lmbda rate_bpp n_pixels h w n_frames psnr_db dec_time_arm_sec dec_time_ups_sec dec_time_syn_sec dec_time_blend_sec dec_time_warp_sec dec_time_coeffgen_sec dec_time_coeffget_sec dec_time_bpred_sec dec_time_all_sec 2 | C-RaceHorses_832x480_30p_yuv420_8b 0.002 0.059436965811965815 119808000 480 832 300 30.662995723006482 1.20275 0.504804 6.1664 0.0 13.9564 0.00016425 0.416296 0.407236 22.8907 3 | C-BasketballDrill_832x480_50p_yuv420_8b 0.002 0.03602688301282051 199680000 480 832 500 33.37046990391618 0.895443 0.774212 10.2698 0.0 22.3952 0.000242806 0.848217 0.621407 36.0354 4 | C-PartyScene_832x480_50p_yuv420_8b 0.002 0.046319511217948715 199680000 480 832 500 29.929224659243687 1.53989 0.743249 10.2718 0.0 22.4064 0.000232271 0.84825 0.61343 36.5314 5 | C-BQMall_832x480_60p_yuv420_8b 0.002 0.03528195112179487 239616000 480 832 600 33.02308034836251 1.31292 0.786781 12.3007 0.0 27.2409 0.00027256 1.00008 0.644901 43.5136 6 | C-RaceHorses_832x480_30p_yuv420_8b 0.0007 0.10517007211538462 119808000 480 832 300 32.942035075888484 2.05217 0.526249 6.17086 0.0 13.9407 0.000173286 0.416046 0.393764 23.659 7 | C-BasketballDrill_832x480_50p_yuv420_8b 0.0007 0.05404166666666667 199680000 480 832 500 35.51053015603565 1.51941 0.821255 10.2723 0.0 22.4671 0.000242846 0.84796 0.561785 36.6006 8 | C-PartyScene_832x480_50p_yuv420_8b 0.0007 0.07917616185897436 199680000 480 832 500 32.348688591958926 2.45402 0.802237 10.2728 0.0 22.5106 0.000236491 0.847983 0.554985 37.6576 9 | C-BQMall_832x480_60p_yuv420_8b 0.0007 0.05403462206196581 239616000 480 832 600 35.39295743387568 2.15503 0.853628 12.3079 0.0 27.2729 0.000264626 1.00007 0.786676 44.5879 10 | C-RaceHorses_832x480_30p_yuv420_8b 0.0002 0.20665291132478633 119808000 480 832 300 35.71226960282842 3.45552 0.543122 6.17528 0.0 13.9171 0.000143409 0.416525 0.414825 25.1932 11 | C-BasketballDrill_832x480_50p_yuv420_8b 0.0002 0.09624667467948718 199680000 480 832 500 38.21121219424274 2.91112 0.873021 10.2777 0.0 22.2604 0.000248008 0.848123 0.612045 37.9044 12 | C-PartyScene_832x480_50p_yuv420_8b 0.0002 0.15117123397435897 199680000 480 832 500 35.07017770130965 3.96916 0.862038 10.2859 0.0 22.3928 0.000252748 0.849705 0.64198 39.1355 13 | C-BQMall_832x480_60p_yuv420_8b 0.0002 0.09533510283119657 239616000 480 832 600 38.04301379759292 3.63495 0.931623 12.3077 0.0 27.27 0.000283349 1.00009 0.668986 46.0542 14 | C-RaceHorses_832x480_30p_yuv420_8b 6e-05 0.413386952457265 119808000 480 832 300 38.34404229751128 5.62217 0.565986 6.17496 0.0 14.0331 0.000158326 0.41686 0.455191 27.5665 15 | C-BasketballDrill_832x480_50p_yuv420_8b 6e-05 0.17821766826923077 199680000 480 832 500 40.7899343109404 4.65844 0.9116 10.2798 0.0 22.43 0.00024499 0.848073 0.550657 39.9109 16 | C-PartyScene_832x480_50p_yuv420_8b 6e-05 0.3016506810897436 199680000 480 832 500 37.77995377540279 6.82915 0.899829 10.2883 0.0 22.415 0.000228582 0.847963 0.640715 42.1483 17 | C-BQMall_832x480_60p_yuv420_8b 6e-05 0.1727040264423077 239616000 480 832 600 40.246139689592155 5.68826 1.0231 12.3306 0.0 27.1291 0.00028414 1.00008 0.845136 48.2617 18 | -------------------------------------------------------------------------------- /coolchic/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | project(ccdec) 3 | 4 | add_executable(ccdec) 5 | 6 | set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}) 7 | 8 | if(WIN32) 9 | 10 | message(STATUS "[ERROR] Cool-chic decoder not yet implemented for Windows...") 11 | 12 | # Check Apple first, then UNIX (Apple + Linux) so that if we enter the UNIX if 13 | # it means that we're on Linux. 14 | elseif(APPLE) 15 | 16 | if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") 17 | 18 | # Changes when compiling for arm64 Apple Mac: 19 | # - Remove all *_avx2.cpp and *_avx512.cpp files 20 | # - Remove the -mfa from the compilation options 21 | # - Remove all the target_link_options... what is this for?? 22 | # 23 | # It only compiles using g++/gcc, not clang which defaults to 24 | # an older version apparently? 25 | # cmake -DCMAKE_C_COMPILER=/opt/homebrew/bin/gcc-13 -DCMAKE_CXX_COMPILER=/opt/homebrew/bin/g++-13 .. 26 | 27 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -g -Wall -Winline") 28 | 29 | target_sources(ccdec PRIVATE ccdecapi.cpp cc-bitstream.cpp cc-contexts.cpp arm_cpu.cpp syn_cpu.cpp BitStream.cpp TDecBinCoderCABAC.cpp Contexts.cpp) 30 | 31 | else() 32 | 33 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -g -Winline") 34 | 35 | # For now, we compile *_avx2.cpp and files, but they are 36 | # excluded from ccdec.cpp using quick & dirty #ifdef __APPLE__ 37 | target_sources(ccdec PRIVATE ccdecapi.cpp cc-bitstream.cpp cc-contexts.cpp arm_cpu.cpp arm_avx2.cpp ups_cpu.cpp ups_avx2.cpp syn_cpu.cpp syn_avx2.cpp warp_common.cpp warp_cpu.cpp warp_avx2.cpp BitStream.cpp TDecBinCoderCABAC.cpp Contexts.cpp common_randomness.cpp) 38 | 39 | set_source_files_properties(arm_avx2.cpp PROPERTIES COMPILE_FLAGS "-mavx2") 40 | set_source_files_properties(ups_avx2.cpp PROPERTIES COMPILE_FLAGS "-mavx2") 41 | set_source_files_properties(syn_avx2.cpp PROPERTIES COMPILE_FLAGS "-mavx2") 42 | set_source_files_properties(warp_avx2.cpp PROPERTIES COMPILE_FLAGS "-mavx2") 43 | 44 | endif() 45 | 46 | elseif(UNIX) 47 | 48 | message(STATUS "Architecture: Linux") 49 | 50 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -g -Wall -std=c++17 -Winline -DCCDEC_EXE -DCCDECAPI_AVX2_OPTIONAL") 51 | 52 | target_sources(ccdec PRIVATE ccdecapi.cpp cc-bitstream.cpp cc-contexts.cpp frame-memory.cpp cc-frame-decoder.cpp arm_cpu.cpp arm_avx2.cpp ups_cpu.cpp ups_avx2.cpp syn_cpu.cpp syn_avx2.cpp warp_common.cpp warp_cpu.cpp warp_avx2.cpp BitStream.cpp TDecBinCoderCABAC.cpp Contexts.cpp common_randomness.cpp) 53 | set(CMAKE_EXE_LINKER_FLAGS "-static") 54 | 55 | set_source_files_properties(warp_avx2.cpp PROPERTIES COMPILE_FLAGS "-mavx2 -mfma") 56 | set_source_files_properties(arm_avx2.cpp PROPERTIES COMPILE_FLAGS "-mavx2 -mfma") 57 | set_source_files_properties(ups_avx2.cpp PROPERTIES COMPILE_FLAGS "-mavx2 -mfma") 58 | set_source_files_properties(syn_avx2.cpp PROPERTIES COMPILE_FLAGS "-mavx2 -mfma") 59 | 60 | endif() 61 | 62 | -------------------------------------------------------------------------------- /docs/source/image_compression/overview.rst: -------------------------------------------------------------------------------- 1 | .. _image_compression_overview: 2 | 3 | Image compression with Cool-chic 4 | ================================ 5 | 6 | Encoding your own image is achieved by using the script ``coolchic/encode.py``. 7 | 8 | .. code:: bash 9 | 10 | (venv) ~/Cool-Chic$ python coolchic/encode.py \ 11 | --input=path_to_my_example \ 12 | --output=bitstream.bin \ 13 | --workdir=./my_temporary_workdir/ \ 14 | --enc_cfg=cfg/enc/intra/fast_10k.cfg \ 15 | --dec_cfg_residue=cfg/dec/intra/mop.cfg \ 16 | --lmbda=0.001 # Typical range is 1e-2 (low rate) to 1e-4 (high rate) 17 | 18 | Unlike the decoding script which only takes input and output arguments, the 19 | encoder has many arguments allowing to tune Cool-chic for your need. 20 | 21 | * :ref:`Encoder configuration ` affects the encoding duration by 22 | changing the training parameters. This is set through the argument 23 | ``--enc_cfg``. Several encoder configuration files are available in ``cfg/enc/``. 24 | 25 | * :ref:`Decoder configuration ` parametrizes the decoder 26 | architecture and complexity. This is set through the argument ``--dec_cfg``. 27 | Several encoder configuration files are available in ``cfg/dec/``. 28 | 29 | Working directory 30 | """"""""""""""""" 31 | 32 | The ``--workdir`` argument is used to specify a folder where all necessary data 33 | will be stored. This includes the encoder logs and the PyTorch model 34 | (``workdir/0000-frame_encoder.pt``). 35 | 36 | .. attention:: 37 | 38 | If present, the PyTorch model inside workdir ``workdir/0000-frame_encoder.pt`` 39 | is reloaded by the ``coolchic/encode.py`` script. In order to encode a new 40 | image using the same workdir, you must first clean out the workdir. 41 | 42 | I/O format 43 | """""""""" 44 | 45 | Cool-chic is able to encode PPM, PNG, YUV420 & YUV 444 files. The naming of YUV files 46 | must comply with the following convention 47 | 48 | .. code:: bash 49 | 50 | --input=_x_p_yuv_b.yuv 51 | 52 | Note that Cool-Chic outputs either `PPM 53 | `_ (and not PNG!) or `YUV 54 | `_ files. 55 | 56 | Rate constraint 57 | """"""""""""""" 58 | 59 | The rate constraint ``--lmbda`` is used to balance the rate and the distortion when encoding an image. 60 | Indeed, Cool-chic parameters are optimized through gradient descent according to the following rate-distortion objective: 61 | 62 | .. math:: 63 | 64 | \mathcal{L} = ||\mathbf{x} - \hat{\mathbf{x}}||^2 + \lambda 65 | (\mathrm{R}(\hat{\mathbf{x}})), \text{ with } 66 | \begin{cases} 67 | \mathbf{x} & \text{the original image}\\ \hat{\mathbf{x}} & 68 | \text{the coded image}\\ \mathrm{R}(\hat{\mathbf{x}}) & 69 | \text{a measure of the rate of } \hat{\mathbf{x}}\\ 70 | \lambda & \text{the rate constraint }\texttt{--lmbda} 71 | \end{cases} -------------------------------------------------------------------------------- /docs/source/results/image/encoding_complexity.rst: -------------------------------------------------------------------------------- 1 | Image encoding complexity 2 | ========================= 3 | 4 | 5 | Number of iterations 6 | """""""""""""""""""" 7 | 8 | As for conventional codecs (e.g. HEVC or VVC), Cool-chic encoding time is 9 | variable. A longer encoding gives better compression performance while a reduced 10 | encoding time results in slightly degraded coding efficiency. 11 | 12 | We present here the impact of the number of encoding iterations on the 13 | compression performance by comparing the results obtained through the :ref:`3 proposed 14 | configurations ` in ``cfg/enc/``: ``fast_10k``, ``medium_30k`` and ``slow_100k``. 15 | We used the ``hop`` :ref:`decoding preset `. 16 | 17 | Kodak 18 | ***** 19 | 20 | .. image:: ../../assets/kodak/perf_complexity_enc.png 21 | :alt: Kodak rd results 22 | 23 | CLIC20 Pro Valid 24 | **************** 25 | 26 | .. image:: ../../assets/clic20-pro-valid/perf_complexity_enc.png 27 | :alt: CLIC20 rd results 28 | 29 | 30 | JVET Class B 31 | ************ 32 | 33 | .. image:: ../../assets/jvet/perf_complexity_enc_classB.png 34 | :alt: JVET class B rd results 35 | 36 | JVET Class C 37 | ************ 38 | 39 | .. image:: ../../assets/jvet/perf_complexity_enc_classC.png 40 | :alt: JVET class C rd results 41 | 42 | JVET Class D 43 | ************ 44 | 45 | .. image:: ../../assets/jvet/perf_complexity_enc_classD.png 46 | :alt: JVET class D rd results 47 | 48 | JVET Class E 49 | ************ 50 | 51 | .. image:: ../../assets/jvet/perf_complexity_enc_classE.png 52 | :alt: JVET class E rd results 53 | 54 | JVET Class F 55 | ************ 56 | 57 | .. image:: ../../assets/jvet/perf_complexity_enc_classF.png 58 | :alt: JVET class F rd results 59 | 60 | JVET All Classes 61 | **************** 62 | 63 | .. image:: ../../assets/jvet/perf_complexity_enc_classBCDEF.png 64 | :alt: JVET class BCDEF rd results 65 | 66 | .. .. _encoding_timing: 67 | .. Encoding time 68 | .. """"""""""""" 69 | 70 | .. The actual time required to perform one encoding iteration depends on the 71 | .. hardware, the image resolution and... the Cool-chic version since more recent versions 72 | .. are usually more optimized. 73 | 74 | .. .. important:: 75 | .. Starting from Cool-chic 3.4.1, ``torch.compile`` is used to significantly reduce the encoding time 76 | 77 | .. Here are a comparison of the encoding time required for 3 different resolutions 78 | .. on different hardwares and Cool-chic versions. This is obtained with the 79 | .. ``medium_30k`` encoding configuration. 80 | 81 | 82 | .. 512x768 image 83 | .. ************* 84 | 85 | .. .. image:: ../../assets/encoding-time/encoding-time-kodak.png 86 | .. :alt: Encoding time on kodak 87 | 88 | 89 | .. 720x1280 image 90 | .. ************** 91 | 92 | .. .. image:: ../../assets/encoding-time/encoding-time-jvet-e.png 93 | .. :alt: Encoding time on JVET E 94 | 95 | .. 1363x2048 image 96 | .. *************** 97 | 98 | .. .. image:: ../../assets/encoding-time/encoding-time-clic.png 99 | .. :alt: Encoding time on CLIC 100 | -------------------------------------------------------------------------------- /docs/source/encoding/preset.rst: -------------------------------------------------------------------------------- 1 | Encoder configuration 2 | ===================== 3 | 4 | As with conventional codecs, there is a trade-off between Cool-chic encoding 5 | time and compression performance. The encoding settings of Cool-chic are set in 6 | a configuration file. Examples of such configuration files are located in ``cfg/enc/``. 7 | They include the following parameters: 8 | 9 | .. list-table:: Parameters relative to the encoder configuration 10 | :widths: 25 50 25 11 | :header-rows: 1 12 | 13 | * - Parameter 14 | - Role 15 | - Example value 16 | * - ``recipe`` 17 | - Training preset 18 | - ``c3x`` 19 | * - ``start_lr`` 20 | - Initial learning rate 21 | - ``1e-2`` 22 | * - ``n_itr`` 23 | - Number of training iterations 24 | - ``1e4``` 25 | * - ``n_train_loops`` 26 | - Number of independent encodings 27 | - ``1``` 28 | 29 | .. tip:: 30 | 31 | Each parameter listed in the configuration file can be overridden through a 32 | command line argument: 33 | 34 | .. code:: bash 35 | 36 | (venv) ~/Cool-Chic python coolchic/encode.py \ 37 | --enc_cfg=enc/cfg/fast_10k.cfg # fast_10k.cfg has start_lr=1e-2 38 | --start_lr=1e-3 # This override the value present in fast_10k.cfg 39 | 40 | .. _encoder_cfg_files: 41 | Some existing configuration files 42 | """"""""""""""""""""""""""""""""" 43 | 44 | Some configuration files are proposed in ``cfg/enc/``. Longer encoding gives 45 | slightly better compression results. We provide comprehensive results for all 46 | encoding configurations on :doc:`the encoding complexity page <../results/image/encoding_complexity>`. 47 | 48 | .. list-table:: Existing encoder configuration files. 49 | :widths: 25 75 50 | :header-rows: 1 51 | 52 | * - Name 53 | - Description 54 | * - ``fast_10k.cfg`` 55 | - Reasonable compression performance & fast training 56 | * - ``medium_30k.cfg`` 57 | - Balance compression performance & training duration 58 | * - ``slow_100k.cfg`` 59 | - Best performance at the cost of a longer training 60 | 61 | Recipes 62 | """"""" 63 | 64 | Cool-chic encoding works with tweakable recipes *i.e.* different training 65 | parameters. Currently available recipes are: 66 | 67 | * ``c3x`` Inspired by `C3: High-performance and low-complexity neural 68 | compression from a single image or video, Kim et al 69 | `_. It is composed of two main phases: 70 | 71 | 1. additive noise model and softround for the latent quantization 72 | 73 | 2. Actual quantization with softround in the backward 74 | 75 | * ``debug`` Extremely fast preset with very bad performance only for debugging purposes. 76 | 77 | All recipes feature a decreasing learning rate starting from ``start_lr``. 78 | 79 | The number of iterations in the first (and longest) phase of the ``c3x`` recipe is 80 | set using ``n_itr``. 81 | 82 | In order to circumvent some training irregularities, it is possible to perform 83 | several independent encoding, keeping only the best one. We call that a training 84 | loop. The number of training loops is set by ``n_train_loops``. 85 | 86 | 87 | -------------------------------------------------------------------------------- /coolchic/cpp/TEncBinCoder.h: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2010-2017, ITU/ISO/IEC 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /** \file TEncBinCoder.h 35 | \brief binary entropy encoder interface 36 | */ 37 | 38 | #ifndef __TENCBINCODER__ 39 | #define __TENCBINCODER__ 40 | 41 | #include "Contexts.h" 42 | #include "BitStream.h" 43 | 44 | //! \ingroup TLibEncoder 45 | //! \{ 46 | 47 | class TEncBinCABAC; 48 | 49 | class TEncBinIf 50 | { 51 | public: 52 | virtual Void init ( OutputBitstream* pcTComBitstream ) = 0; 53 | virtual Void uninit () = 0; 54 | 55 | virtual Void start () = 0; 56 | virtual Void finish () = 0; 57 | 58 | virtual Void encodeBin ( BinProbModel_Std& rcCtxModel, unsigned bin, bool d_update = false ) = 0; 59 | virtual Void encodeExGolomb ( unsigned val, unsigned count ) = 0; 60 | virtual Void encodeBinEP ( UInt uiBin ) = 0; 61 | virtual Void encodeBinsEP ( unsigned uiBins, unsigned numBins ) = 0; 62 | virtual Void encodeBinTrm ( UInt uiBin ) = 0; 63 | 64 | virtual Void align () = 0; 65 | 66 | virtual ~TEncBinIf() {} 67 | }; 68 | 69 | //! \} 70 | 71 | #endif 72 | 73 | -------------------------------------------------------------------------------- /toolbox/toolbox/common/io/image.py: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 2 | # SPDX-License-Identifier: BSD 3-Clause "New" 3 | # 4 | # This software is distributed under the BSD-3-Clause license. 5 | # 6 | # Authors: see CONTRIBUTORS.md 7 | 8 | import numpy as np 9 | from common.io.png import is_png, read_png, write_png 10 | from common.io.ppm import PPM_POSSIBLE_BITDEPTH, _parse_header_ppm, is_ppm, read_ppm, write_ppm 11 | 12 | 13 | def is_image(file_path: str) -> bool: 14 | """Return True if the file is a PNG file or a PPM file 15 | 16 | Args: 17 | file_path (str): File to be checked 18 | 19 | Returns: 20 | bool: True if file is a png or ppm 21 | """ 22 | 23 | return is_png(file_path) or is_ppm(file_path) 24 | 25 | 26 | def read_image(file_path: str) -> np.ndarray: 27 | """Read an image (either PNG or PPM). Return a numpy array [H, W, 3] 28 | containing the image data rescaled into [0., 1.]. 29 | 30 | Args: 31 | file_path: Path to the image to be read. 32 | 33 | Returns: 34 | np.ndarray: Image data. 35 | """ 36 | 37 | assert is_image(file_path), ( 38 | f"read_image is only possible on image. Input file is {file_path}." 39 | ) 40 | 41 | if is_png(file_path): 42 | return read_png(file_path) 43 | 44 | if is_ppm(file_path): 45 | return read_ppm(file_path) 46 | 47 | 48 | def write_image( 49 | data: np.ndarray, file_path: str, bitdepth: PPM_POSSIBLE_BITDEPTH = 8 50 | ) -> None: 51 | """Write a numpy array as an image file. The numpy array must be 52 | in [0., 1.] with a shape of [H, W, 3]. The extension of the desired 53 | file_path (.png or .ppm) determines the output format. 54 | 55 | In the case of .ppm files, the bitdepth can be specified. 56 | 57 | Args: 58 | data: Numpy array to store in a png file. Values are in 59 | [0., 1.] and shape is [H, W, 3] 60 | file_path: Path where the data are stored 61 | bitdepth: Only for PPM files, desired output bitdepth. 62 | """ 63 | 64 | assert is_image(file_path), ( 65 | f"read_image is only possible on image. Input file is {file_path}." 66 | ) 67 | 68 | if is_png(file_path): 69 | if bitdepth != 8: 70 | print( 71 | f"A bitdepth != 8 is specified (bitdepth={bitdepth}). This is" 72 | "ignored for PNG files which always have 8-bit data." 73 | ) 74 | 75 | return write_png(data, file_path) 76 | 77 | if is_ppm(file_path): 78 | return write_ppm(data, file_path, bitdepth=bitdepth) 79 | 80 | 81 | def get_bitdepth_image(file_path: str) -> PPM_POSSIBLE_BITDEPTH: 82 | """Return the bitdepth of a given image. In case of PNG, this is always 83 | 8. But it can varies for PPM. 84 | 85 | Args: 86 | file_path (str): Path of the file whose bitdepth is returned. 87 | 88 | Returns: 89 | PPM_POSSIBLE_BITDEPTH: List of possible bitdepth 90 | """ 91 | assert is_image(file_path), ( 92 | f"get_bitdepth_image is only possible on image. Input file is {file_path}." 93 | ) 94 | 95 | # ! Pillow only reads 8-bit png 96 | if is_png(file_path): 97 | return 8 98 | 99 | if is_ppm(file_path): 100 | _, info = _parse_header_ppm(file_path) 101 | return info["bitdepth"] 102 | -------------------------------------------------------------------------------- /coolchic/cpp/TDecBinCoder.h: -------------------------------------------------------------------------------- 1 | /* The copyright in this software is being made available under the BSD 2 | * License, included below. This software may be subject to other third party 3 | * and contributor rights, including patent rights, and no such rights are 4 | * granted under this license. 5 | * 6 | * Copyright (c) 2010-2017, ITU/ISO/IEC 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright notice, 13 | * this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright notice, 15 | * this list of conditions and the following disclaimer in the documentation 16 | * and/or other materials provided with the distribution. 17 | * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may 18 | * be used to endorse or promote products derived from this software without 19 | * specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 | * THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /** \file TDecBinCoder.h 35 | \brief binary entropy decoder interface 36 | */ 37 | 38 | #ifndef __TDECBINCODER__ 39 | #define __TDECBINCODER__ 40 | 41 | #include "Contexts.h" 42 | #include "BitStream.h" 43 | 44 | #if RExt__DECODER_DEBUG_BIT_STATISTICS 45 | class TComCodingStatisticsClassType; 46 | #endif 47 | 48 | //! \ingroup TLibDecoder 49 | //! \{ 50 | class TDecBinCABAC; 51 | 52 | class TDecBinIf 53 | { 54 | public: 55 | virtual Void init ( InputBitstream* pcTComBitstream ) = 0; 56 | virtual Void uninit () = 0; 57 | 58 | virtual Void start () = 0; 59 | virtual Void finish () = 0; 60 | 61 | virtual UInt decodeBin ( BinProbModel_Std& rcCtxModel, bool do_update = false ) = 0; 62 | virtual UInt decodeBinEP ( ) = 0; 63 | virtual UInt decodeBinsEP ( Int numBins ) = 0; 64 | 65 | virtual Void align () = 0; 66 | 67 | virtual UInt decodeBinTrm ( ) = 0; 68 | virtual Int decodeExGolomb(Int count) = 0; 69 | virtual Void xReadPCMCode ( UInt uiLength, UInt& ruiCode) = 0; 70 | 71 | virtual ~TDecBinIf() {} 72 | 73 | virtual TDecBinCABAC* getTDecBinCABAC () { return 0; } 74 | virtual const TDecBinCABAC* getTDecBinCABAC () const { return 0; } 75 | }; 76 | 77 | //! \} 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /coolchic/cpp/frame-memory.h: -------------------------------------------------------------------------------- 1 | 2 | #include "common.h" 3 | 4 | // P is expected to be int32_t or float 5 | // underlying buffer data is for the moment just int32_t. 6 | template 7 | struct frame_memory 8 | { 9 | buffer

raw_frame; 10 | int origin_idx; 11 | int h; 12 | int w; 13 | int pad; 14 | int planes; 15 | int stride; 16 | int plane_stride; 17 | public: 18 | frame_memory(): 19 | origin_idx(0), 20 | h(0), 21 | w(0), 22 | pad(0), 23 | planes(0), 24 | stride(0), 25 | plane_stride(0) 26 | {}; 27 | ~frame_memory() {}; 28 | public: 29 | void update_to(int frame_h, int frame_w, int frame_pad, int frame_planes) 30 | { 31 | h = frame_h; 32 | w = frame_w; 33 | pad = frame_pad; 34 | planes = frame_planes; 35 | stride = frame_pad+frame_w+frame_pad; 36 | plane_stride = (frame_pad+frame_h+frame_pad)*stride; 37 | origin_idx = frame_pad*stride+frame_pad; 38 | raw_frame.update_to(frame_planes*plane_stride); 39 | } 40 | void update_to(struct frame_memory &src) { update_to(src.h, src.w, src.pad, src.planes); } 41 | void copy_from(struct frame_memory const &src, int nplanes) { update_to(src.h, src.w, src.pad, nplanes); memcpy(raw_frame.data, src.raw_frame.data, nplanes*plane_stride*sizeof(raw_frame.data[0])); } 42 | void copy_from(struct frame_memory const &src) { copy_from(src, src.planes); } 43 | P *raw() { return raw_frame.data; } 44 | P const *const_raw() const { return (P const *)raw_frame.data; } 45 | P const *const_origin() const { return const_raw()+origin_idx; } 46 | P *origin() { return raw()+origin_idx; } 47 | P *plane_origin(int plane = 0) { return origin()+plane*plane_stride; } 48 | P const *const_plane_origin(int plane = 0) const { return const_origin()+plane*plane_stride; } 49 | P *plane_pixel(int plane, int y, int x) { return plane_origin(plane)+y*stride+x; } 50 | P const *const_plane_pixel(int plane, int y, int x) const { return const_plane_origin(plane)+y*stride+x; } 51 | P *pad_origin(int plane, int pad) { return pad_origin(plane, pad, pad); } 52 | P *pad_origin(int plane, int padlr, int padtb) { return raw() + origin_idx-padtb*stride-padlr + plane*plane_stride; } 53 | #if 0 54 | void print_ranges(char const *msg, int nplanes, int precision) 55 | { 56 | int minval = plane_origin(0)[0]; 57 | int maxval = plane_origin(0)[0]; 58 | for (int p = 0; p < nplanes; p++) 59 | for (int y = 0; y < h; y++) 60 | for (int x = 0; x < w; x++) 61 | { 62 | if (plane_origin(p)[y*stride+x] < minval) 63 | minval = plane_origin(p)[y*stride+x]; 64 | else if (plane_origin(p)[y*stride+x] > maxval) 65 | maxval = plane_origin(p)[y*stride+x]; 66 | } 67 | printf("%s: minval=%g maxval=%g\n", msg == NULL ? "" : msg, (float)minval/(1<getNumberOfWrittenBits() + 8 * m_numBufferedBytes + 23 - m_bitsLeft); 66 | } 67 | 68 | 69 | Void encodeBin ( BinProbModel_Std &probModel, unsigned bin, bool d_update = false ); 70 | Void encodeBinsEP ( unsigned bins, unsigned numBins ); 71 | Void encodeBinEP ( unsigned bin ); 72 | Void encodeExGolomb ( unsigned val, unsigned count ); 73 | Void encodeBinTrm ( unsigned bin ); 74 | 75 | Void align (); 76 | Void encodeAlignedBinsEP( unsigned binValues, unsigned numBins ); 77 | 78 | private: 79 | Void writeOut(); 80 | 81 | OutputBitstream *m_bitstream; 82 | uint32_t m_low; 83 | uint32_t m_range; 84 | uint32_t m_bufferedByte; 85 | int32_t m_numBufferedBytes; 86 | int32_t m_bitsLeft; 87 | }; 88 | 89 | //! \} 90 | 91 | #endif 92 | 93 | -------------------------------------------------------------------------------- /coolchic/cpp/warp_common.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | #include 11 | #include // timing. 12 | #include 13 | 14 | #include "common.h" 15 | #include "warp_common.h" 16 | 17 | // !!! global coeff storage for now. 18 | int g_coeff_table_motion_q_shift = -1; 19 | int g_coeff_table_ntaps = -1; 20 | float *g_coeff_table = NULL; // index with [quantval * ntaps]. 21 | 22 | template 23 | inline P cubic_conv_near(P x, P A) 24 | { 25 | return ((A+2)*x - (A+3))*x*x + 1; 26 | } 27 | 28 | template 29 | inline P cubic_conv_far(P x, P A) 30 | { 31 | return ((A*x - 5*A)*x + 8*A)*x - 4*A; 32 | } 33 | 34 | template 35 | inline void sinc_generate_coeffs(P coeffs[NTAPS], P t) 36 | { 37 | P pi_N = M_PI/NTAPS; 38 | 39 | P delta_i = NTAPS/2+t-1; 40 | for (int i = 1; i <= NTAPS; i++, delta_i -= 1.0) 41 | { 42 | if (delta_i != 0) 43 | coeffs[i-1] = cos(pi_N*delta_i)*sin(M_PI*delta_i)/(M_PI*delta_i); 44 | else 45 | coeffs[i-1] = 1.0; 46 | } 47 | } 48 | 49 | template 50 | inline void bicubic_generate_coeffs(P coeffs[4], P t) 51 | { 52 | P tleft = t; 53 | P const A = -0.75; 54 | coeffs[0] = cubic_conv_far(tleft+1, A); 55 | coeffs[1] = cubic_conv_near(tleft, A); 56 | P tright = 1-t; 57 | coeffs[2] = cubic_conv_near(tright, A); 58 | coeffs[3] = cubic_conv_far(tright+1, A); 59 | } 60 | 61 | template 62 | inline void bilinear_generate_coeffs(P coeffs[2], P t) 63 | { 64 | coeffs[0] = 1-t; 65 | coeffs[1] = t; 66 | } 67 | 68 | template 69 | void generate_coeffs(int motion_q_shift) 70 | { 71 | if (g_coeff_table_motion_q_shift == motion_q_shift && g_coeff_table_ntaps == NTAPS) 72 | return; // nothing to do. 73 | 74 | // generate all coeffs for quantized motion. 75 | delete [] g_coeff_table; 76 | g_coeff_table = new float[NTAPS<(&g_coeff_table[q*NTAPS], ((float)q)/(1<(&g_coeff_table[q*NTAPS], ((float)q)/(1<(&g_coeff_table[q*NTAPS], ((float)q)/(1<(int motion_q_shift); 99 | template void generate_coeffs(int motion_q_shift); 100 | template void generate_coeffs(int motion_q_shift); 101 | template void generate_coeffs(int motion_q_shift); 102 | template void generate_coeffs(int motion_q_shift); 103 | template void generate_coeffs(int motion_q_shift); 104 | template void generate_coeffs(int motion_q_shift); 105 | template void generate_coeffs(int motion_q_shift); 106 | -------------------------------------------------------------------------------- /docs/source/encoding/video.rst: -------------------------------------------------------------------------------- 1 | Video coding configuration 2 | ========================== 3 | 4 | .. attention:: 5 | 6 | 🛑 Cool-chic 3.2 and 3.3 temporarily disable video coding. If you really want to 7 | compress videos you can 8 | 9 | * Go back to 3.1: ``git clone --branch v3.1 10 | https://github.com/Orange-OpenSource/Cool-Chic.git`` 11 | 12 | * Wait for Cool-chic 4.0 for better and faster video coding 😉. 13 | 14 | 15 | .. The video coding configuration is set through the following arguments 16 | 17 | .. * ``--intra_period`` 18 | 19 | .. * ``--p_period`` 20 | 21 | 22 | .. Cool-chic is a video codec implementing 3 different type of frames 23 | 24 | .. * I (intra) frames have no reference. They can be used for image coding 25 | 26 | .. * P (inter) frames have a single reference. 27 | 28 | .. * B (inter) frames have two references 29 | 30 | 31 | .. Cool-chic always encodes a Group Of Pictures (GOP), consisting in 1 intra 32 | .. frame followed by 0 to 255 inter frame(s). 33 | 34 | .. .. tip:: 35 | 36 | .. Coding an image is achieved by using a single-frame GOP with only an intra frame. 37 | 38 | 39 | .. Intra period 40 | .. """""""""""" 41 | 42 | .. A GOP starts with an intra frame and followed by an arbitrary number of inter (P 43 | .. or B) frames. The number of frames in the GOP and the number of frames encoded 44 | .. by Cool-chic is thus: intra period + 1: 45 | 46 | .. .. code:: bash 47 | 48 | .. # This codes 9 frames from the video 49 | .. # number_of_coded_frames = number_of_frames_in_gop = intra_period + 1 50 | .. (venv) python3 src/encode.py --intra_period=8 --input=xxx.yuv 51 | 52 | 53 | .. P-period 54 | .. """""""" 55 | 56 | .. Both GOPs below have the same ``--intra_period=8`` but have a different ``--p_period`` 57 | 58 | .. .. code:: bash 59 | 60 | .. # A low-delay P configuration 61 | .. # I0 ---> P1 ---> P2 ---> P3 ---> P4 ---> P5 ---> P6 ---> P7 ---> P8 62 | .. python3 src/encode.py --intra_period=8 --p_period=1 --input=xxx.yuv 63 | 64 | .. # A hierarchichal Random Access configuration 65 | .. # I0 -----------------------------------------------------> P8 66 | .. # \-------------------------> B4 <-------------------------/ 67 | .. # \----------> B2 <---------/ \----------> B6 <----------/ 68 | .. # \--> B1 <--/ \--> B3 <--/ \--> B5 <--/ \--> B7 <--/ 69 | .. python3 src/encode.py --intra_period=8 --p_period=8 --input=xxx.yuv 70 | 71 | .. Note the introduction of the ``--p_period`` argument in the command line. This 72 | .. sets the distance between the ``IO`` frame and the successive ``P`` frames. 73 | .. Reducing the temporal distance alleviates the motion compensation process, which 74 | .. can be useful. It can also enables more complex GOP structure such as: 75 | 76 | .. .. code:: python 77 | 78 | .. # There is no more prediction from I0 to P8. Instead the GOP in split in 79 | .. # half so that there is no inter frame with reference further than --p_period 80 | 81 | .. # I0 -----------------------> P4 ------------------------> P8 82 | .. # \----------> B2 <---------/ \----------> B6 <----------/ 83 | .. # \--> B1 <--/ \--> B3 <--/ \--> B5 <--/ \--> B7 <--/ 84 | .. python3 src/encode.py --intra_period=8 --p_period=4 --input=xxx.yuv 85 | 86 | 87 | Image coding 88 | """""""""""" 89 | 90 | To achieve plain image coding *i.e.* compression a single standalone intra 91 | frame simply set the intra period and P period to zero. 92 | 93 | .. code:: python 94 | 95 | # Image coding, input could also be a .yuv file in such case, it 96 | # would only encode the first video frame. 97 | python3 src/encode.py --intra_period=0 --p_period=0 --input=xxx.png -------------------------------------------------------------------------------- /coolchic/cpp/cc-bitstream.h: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | 11 | /* 12 | * bitstream reading. 13 | */ 14 | // !!! enum FRAME_DATA_TYPE 15 | struct cc_bs_gop_header 16 | { 17 | int n_bytes_header; 18 | int img_h; 19 | int img_w; 20 | int frame_data_type; // 0 rgb, 1 yuv420, 2 yuv444 21 | int output_bitdepth; 22 | //int intra_period; 23 | //int p_period; 24 | }; 25 | 26 | struct cc_bs_syn_layer { 27 | int n_out_ft; 28 | int ks; 29 | bool residual; 30 | bool relu; 31 | }; 32 | 33 | // quantization information for module weights or biases. Possibly multiple layers encoded. 34 | struct cc_bs_layer_quant_info 35 | { 36 | int q_step_index_nn_weight; 37 | int q_step_index_nn_bias; 38 | int scale_index_nn_weight; 39 | int scale_index_nn_bias; 40 | int n_bytes_nn_weight; 41 | int n_bytes_nn_bias; 42 | }; 43 | 44 | struct cc_bs_frame_coolchic 45 | { 46 | bool latents_zero; 47 | int n_hidden_layers_arm; 48 | int dim_arm; 49 | 50 | int n_ups_kernel; 51 | int ups_k_size; 52 | int n_ups_preconcat_kernel; 53 | int ups_preconcat_k_size; 54 | 55 | int n_syn_layers; 56 | std::vector layers_synthesis; 57 | struct cc_bs_layer_quant_info arm_lqi; 58 | struct cc_bs_layer_quant_info ups_lqi; 59 | struct cc_bs_layer_quant_info syn_lqi; 60 | 61 | int hls_sig_blksize; 62 | 63 | int n_latent_n_resolutions; 64 | int noise_n_2d_grid; 65 | int latent_n_2d_grid; 66 | std::vector n_ft_per_noise; 67 | std::vector n_ft_per_latent; 68 | std::vector n_bytes_per_latent; 69 | int n_leading_zero_feature_layers; 70 | 71 | // weights, biases and latents. BAC coded. 72 | std::vector m_arm_weights_hevc; 73 | std::vector m_arm_biases_hevc; 74 | std::vector m_ups_weights_hevc; // both lb and hb 75 | std::vector m_ups_biases_hevc; // both lb and hb 76 | std::vector m_syn_weights_hevc; // all branches 77 | std::vector m_syn_biases_hevc; // all branches 78 | std::vector> m_latents_hevc; 79 | 80 | public: 81 | void copy_archi_from(struct cc_bs_frame_coolchic const &src, int topology_copy_bits); 82 | void print(); 83 | }; 84 | 85 | // topology-copy bits. 86 | #define TOP_COPY_ARM 0 87 | #define TOP_COPY_UPS 1 88 | #define TOP_COPY_SYN 2 89 | #define TOP_COPY_LAT 3 90 | 91 | struct cc_bs_frame_header 92 | { 93 | short n_bytes_header; 94 | int display_index; 95 | unsigned char frame_type; // 'I', 'P', 'B' 96 | int topology_copy[2]; // bits. arm, ups, syn, lat 97 | bool latents_zero[2]; 98 | int global_flow[2][2]; // [ref0|ref1][y|x] 99 | int warp_filter_length; 100 | // frame type giving number of coolchics. and references. 101 | }; 102 | 103 | struct cc_bs_frame { 104 | struct cc_bs_frame_header m_frame_header; 105 | std::vector m_coolchics; // residue, motion 106 | }; 107 | 108 | class cc_bs { 109 | public: 110 | cc_bs() { m_f = NULL; } 111 | ~cc_bs() { if (m_f != NULL) fclose(m_f); } 112 | bool open(std::string filename, int verbosity = 0); 113 | struct cc_bs_frame *decode_frame(struct cc_bs_frame const *prev_coded_I_frame_symbols, struct cc_bs_frame const *prev_coded_frame_symbols, int verbosity = 0); 114 | private: 115 | bool read_gop_header(int verbosity = 0); 116 | 117 | public: 118 | std::string m_filename; 119 | struct cc_bs_gop_header m_gop_header; 120 | private: 121 | FILE *m_f; 122 | }; 123 | -------------------------------------------------------------------------------- /coolchic/enc/io/io.py: -------------------------------------------------------------------------------- 1 | from enc.utils.codingstructure import FrameData 2 | from enc.io.types import FRAME_DATA_TYPE, POSSIBLE_BITDEPTH 3 | from enc.io.format.ppm import read_ppm, write_ppm 4 | from enc.io.format.yuv import read_yuv, write_yuv 5 | from enc.io.format.png import read_png, write_png 6 | 7 | import os 8 | 9 | 10 | def load_frame_data_from_file(file_path: str, idx_display_order: int) -> FrameData: 11 | """Load the idx_display_order-th frame from a .yuv file or .png file. For the latter, 12 | idx_display_order must be equal to 0 as there is only one frame in a png. 13 | 14 | Args: 15 | file_path (str): Absolute path of the file from which the frame is loaded. 16 | idx_display_order (int): Index of the frame in display order 17 | 18 | Returns: 19 | FrameData: The loaded frame, wrapped as a FrameData object. 20 | """ 21 | POSSIBLE_EXT = [".yuv", ".png", ".ppm"] 22 | assert file_path[-4:] in POSSIBLE_EXT, ( 23 | "The function load_frame_data_from_file() expects a file ending with " 24 | f"{POSSIBLE_EXT}. Found {file_path}" 25 | ) 26 | 27 | if file_path.endswith(".yuv"): 28 | # ! We only consider yuv420 and 444 planar 29 | bitdepth: POSSIBLE_BITDEPTH = 8 if "_8b" in file_path else 10 30 | frame_data_type: FRAME_DATA_TYPE = "yuv420" if "420" in file_path else "yuv444" 31 | data = read_yuv(file_path, idx_display_order, frame_data_type, bitdepth) 32 | 33 | elif file_path.endswith(".png"): 34 | frame_data_type: FRAME_DATA_TYPE = "rgb" 35 | data, bitdepth = read_png(file_path) 36 | 37 | elif file_path.endswith(".ppm"): 38 | frame_data_type: FRAME_DATA_TYPE = "rgb" 39 | data, bitdepth = read_ppm(file_path) 40 | 41 | return FrameData(bitdepth, frame_data_type, data) 42 | 43 | def save_frame_data_to_file(frame_data: FrameData, file_path: str) -> None: 44 | """Save the data of a FrameData into a PNG, PPM or YUV file. 45 | file_path extension must match the FrameData type e.g. PNG or PPM for 46 | RGB and YUV for YUV420 or YUV444 47 | 48 | Args: 49 | frame_data (FrameData): The data to save 50 | file_path (str): Absolute path of the file from which the frame is stored. 51 | """ 52 | 53 | POSSIBLE_EXT = [".yuv", ".png", ".ppm"] 54 | 55 | cur_extension = os.path.splitext(file_path)[1] 56 | assert cur_extension in POSSIBLE_EXT, ( 57 | "The function save_frame_data_to_file() expects a file ending with " 58 | f"{POSSIBLE_EXT}. Found {file_path}" 59 | ) 60 | 61 | if cur_extension == ".png": 62 | 63 | assert frame_data.frame_data_type == "rgb", ( 64 | "The function save_frame_data_to_file() can only save a RGB data " 65 | f"into a PNG file. Found frame_data_type = {frame_data.frame_data_type}." 66 | ) 67 | 68 | assert frame_data.bitdepth == 8, ( 69 | "The function save_frame_data_to_file() can only write 8-bit data " 70 | f"into a PNG file. Found bitdepth = {frame_data.bitdepth}." 71 | ) 72 | 73 | write_png(frame_data.data, file_path) 74 | 75 | elif cur_extension == ".ppm": 76 | 77 | assert frame_data.frame_data_type == "rgb", ( 78 | "The function save_frame_data_to_file() can only save a RGB data " 79 | f"into a PPM file. Found frame_data_type = {frame_data.frame_data_type}." 80 | ) 81 | 82 | write_ppm(frame_data.data, frame_data.bitdepth, file_path, norm=True) 83 | 84 | elif cur_extension == ".yuv": 85 | 86 | assert frame_data.frame_data_type in ["yuv420", "yuv444"], ( 87 | "The function save_frame_data_to_file() can only save a YUV data " 88 | f"into a YUV file. Found frame_data_type = {frame_data.frame_data_type}." 89 | ) 90 | 91 | write_yuv( 92 | frame_data.data, 93 | frame_data.bitdepth, 94 | frame_data.frame_data_type, 95 | file_path, 96 | norm=True, 97 | ) 98 | -------------------------------------------------------------------------------- /results/v1.0/image-kodak.tsv: -------------------------------------------------------------------------------- 1 | seq lambda rate_bpp psnr_db 2 | kodim01 0.0001 2.469584147 40.53910997 3 | kodim01 0.0005 1.482930501 34.79325625 4 | kodim01 0.004 0.371032715 26.98512253 5 | kodim01 0.02 0.110860189 23.67770195 6 | kodim02 0.0001 1.342793783 40.38887902 7 | kodim02 0.0005 0.523701986 35.40175272 8 | kodim02 0.004 0.101908366 30.48660185 9 | kodim02 0.02 0.031840007 27.7014346 10 | kodim03 0.0001 1.027038574 42.22406477 11 | kodim03 0.0005 0.513041178 37.76341312 12 | kodim03 0.004 0.11151123 31.08553512 13 | kodim03 0.02 0.043477376 28.4668662 14 | kodim04 0.0001 1.537780762 40.73435834 15 | kodim04 0.0005 0.639424642 35.47234404 16 | kodim04 0.004 0.155619303 30.45324262 17 | kodim04 0.02 0.049173991 27.32964532 18 | kodim05 0.0001 2.573262533 40.42537536 19 | kodim05 0.0005 1.501566569 34.57673196 20 | kodim05 0.004 0.567728678 27.6472157 21 | kodim05 0.02 0.173522949 23.01587185 22 | kodim06 0.0001 2.033793132 40.83441917 23 | kodim06 0.0005 1.133076986 35.78012387 24 | kodim06 0.004 0.291524251 27.79710117 25 | kodim06 0.02 0.063496908 23.97080447 26 | kodim07 0.0001 1.195902507 41.70912708 27 | kodim07 0.0005 0.606953939 37.22418627 28 | kodim07 0.004 0.224222819 31.49127683 29 | kodim07 0.02 0.085469564 27.02525533 30 | kodim08 0.0001 2.617289225 40.16210632 31 | kodim08 0.0005 1.561462402 34.93540073 32 | kodim08 0.004 0.607767741 27.40767921 33 | kodim08 0.02 0.209248861 22.89803459 34 | kodim09 0.0001 1.077982585 40.64710385 35 | kodim09 0.0005 0.547139486 37.18332734 36 | kodim09 0.004 0.153503418 31.32935602 37 | kodim09 0.02 0.061136882 27.683776 38 | kodim10 0.0001 1.142110189 40.57941058 39 | kodim10 0.0005 0.573425293 37.00805862 40 | kodim10 0.004 0.156840007 31.1179352 41 | kodim10 0.02 0.053894043 26.96381287 42 | kodim11 0.0001 1.909362793 40.91540181 43 | kodim11 0.0005 0.952575684 35.26323899 44 | kodim11 0.004 0.220072428 28.34643549 45 | kodim11 0.02 0.069437663 25.27755628 46 | kodim12 0.0001 1.253682454 41.4734309 47 | kodim12 0.0005 0.520609538 36.3074744 48 | kodim12 0.004 0.10736084 31.03826425 49 | kodim12 0.02 0.046325684 28.58337272 50 | kodim13 0.0001 3.289652507 39.88684436 51 | kodim13 0.0005 2.018656413 34.14664146 52 | kodim13 0.004 0.652689616 26.13924211 53 | kodim13 0.02 0.166280111 21.86570778 54 | kodim14 0.0001 2.313822428 40.185272 55 | kodim14 0.0005 1.300638835 34.68472408 56 | kodim14 0.004 0.345479329 28.17953605 57 | kodim14 0.02 0.103780111 24.31537134 58 | kodim15 0.0001 1.446146647 41.0023212 59 | kodim15 0.0005 0.621846517 36.03045367 60 | kodim15 0.004 0.152282715 30.35788543 61 | kodim15 0.02 0.054789225 27.56887732 62 | kodim16 0.0001 1.452982585 41.46564818 63 | kodim16 0.0005 0.684753418 35.97038521 64 | kodim16 0.004 0.150004069 29.27668491 65 | kodim16 0.02 0.038024902 26.68567615 66 | kodim17 0.0001 1.341491699 40.68021983 67 | kodim17 0.0005 0.652119954 36.44249056 68 | kodim17 0.004 0.187845866 30.56590217 69 | kodim17 0.02 0.0684611 26.96822234 70 | kodim18 0.0001 2.344828288 39.77227659 71 | kodim18 0.0005 1.208109538 34.43020441 72 | kodim18 0.004 0.414245605 28.27482355 73 | kodim18 0.02 0.080749512 23.73600679 74 | kodim19 0.0001 1.6465861 40.42748897 75 | kodim19 0.0005 0.884134928 35.45135576 76 | kodim19 0.004 0.214050293 29.23246237 77 | kodim19 0.02 0.073018392 25.12476496 78 | kodim20 0.0001 1.158630371 41.42865082 79 | kodim20 0.0005 0.67010498 37.25017098 80 | kodim20 0.004 0.151224772 30.83869031 81 | kodim20 0.02 0.058369954 27.36900784 82 | kodim21 0.0001 1.664489746 40.43748571 83 | kodim21 0.0005 0.98651123 36.19754593 84 | kodim21 0.004 0.277038574 28.58011331 85 | kodim21 0.02 0.080342611 24.68999839 86 | kodim22 0.0001 1.999776204 40.24505273 87 | kodim22 0.0005 0.903177897 34.60842197 88 | kodim22 0.004 0.206481934 28.71782381 89 | kodim22 0.02 0.059997559 25.61837716 90 | kodim23 0.0001 0.950622559 41.60415681 91 | kodim23 0.0005 0.449157715 37.85670649 92 | kodim23 0.004 0.141377767 32.23689535 93 | kodim23 0.02 0.055277507 28.14690904 94 | kodim24 0.0001 2.19354248 40.85353295 95 | kodim24 0.0005 1.239522298 35.19994718 96 | kodim24 0.004 0.400817871 28.33737331 97 | kodim24 0.02 0.11126709 23.79782389 98 | -------------------------------------------------------------------------------- /coolchic/cpp/arm_cpu.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Software Name: Cool-Chic 3 | SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 4 | SPDX-License-Identifier: BSD 3-Clause "New" 5 | 6 | This software is distributed under the BSD-3-Clause license. 7 | Authors: see CONTRIBUTORS.md 8 | */ 9 | 10 | #include "TDecBinCoderCABAC.h" 11 | #include "common.h" 12 | #include "cc-contexts.h" 13 | #include "cc-bac.h" 14 | #include "arm_cpu.h" 15 | 16 | // generic: nctxts (8,16,24,32), hiddenlayers (0,1,2) 17 | // chains two 16_16, 16_16, final 16_2 18 | void custom_conv_11_int32_cpu_X_X_X(weights_biases *kwtX_n_n, weights_biases *kbX_n, // kwtX_n_n[n_hidden_layers] -- kernel weights, transposed. 19 | weights_biases *kwOUT_n_2, weights_biases *kbOUT_2, // _n_2, weights not transposed. 20 | int32_t *context_indicies, int32_t n_contexts, int32_t n_hidden_layers, 21 | int32_t *SRC, 22 | int src_h, int src_w, int src_pad, 23 | BACContext &bac_context 24 | ) 25 | { 26 | int const n_inout = n_contexts; 27 | int const n_final_out = 2; 28 | 29 | int32_t *src = SRC; 30 | int32_t ioX[2][32]; // buffers used for input and output. 31 | 32 | for (int y = 0; y < src_h; y++, src += src_pad+src_pad) // pads are: eol of this, and bol of next. 33 | for (int x = 0; x < src_w; x++, src++) 34 | { 35 | if (!bac_coded(bac_context, y, x)) 36 | { 37 | src[0] = 0; 38 | continue; 39 | } 40 | int use_left = 1; 41 | if (bac_flat(bac_context, y, x, use_left)) 42 | { 43 | if (use_left) 44 | src[0] = src[-1]; 45 | else 46 | src[0] = src[-(src_w+src_pad+src_pad)]; 47 | continue; 48 | } 49 | 50 | int32_t *inputs = &ioX[0][0]; // switches in outputsX 51 | int32_t *outputs = &ioX[0][0]; // switches in outputsX 52 | 53 | // load input. 54 | for (int i = 0; i < n_inout; i++) 55 | { 56 | inputs[i] = src[context_indicies[i]]; // gather 57 | } 58 | 59 | for (int hl = 0; hl < n_hidden_layers; hl++) 60 | { 61 | inputs = &ioX[(hl+0)%2][0]; 62 | outputs = &ioX[(hl+1)%2][0]; 63 | // operate the first kwt. 64 | int32_t *kw = kwtX_n_n[hl].data; 65 | int32_t *kb = kbX_n[hl].data; 66 | 67 | for (int i = 0; i < n_inout; i++) 68 | outputs[i] = kb[i] + inputs[i]*ARM_SCALE; // residual == 1 69 | for (int il = 0; il < n_inout; il++, kw += n_inout) 70 | { 71 | for (int i = 0; i < n_inout; i++) 72 | outputs[i] += inputs[il]*kw[i]; 73 | } 74 | for (int i = 0; i < n_inout; i++) 75 | { 76 | if (outputs[i] < 0) 77 | outputs[i] = 0; 78 | else 79 | outputs[i] = (outputs[i]+(ARM_SCALE/2)) >> ARM_PRECISION; 80 | } 81 | } 82 | 83 | // FINAL 24 -> 2 84 | int32_t out[2]; 85 | int32_t *kw = kwOUT_n_2->data; 86 | int32_t *kb = kbOUT_2->data; 87 | for (int ol = 0; ol < n_final_out; ol++, kw += n_inout) 88 | { 89 | int32_t sum = kb[ol]; 90 | for (int il = 0; il < n_inout; il++) 91 | sum += outputs[il]*kw[il]; 92 | if (sum < 0) 93 | sum = -((-sum+ARM_SCALE/2) >> ARM_PRECISION); 94 | else 95 | sum = (sum+ARM_SCALE/2) >> ARM_PRECISION; 96 | out[ol] = sum; 97 | } 98 | 99 | // bac it. 100 | int xx = decode_latent_layer_bac_single( 101 | bac_context, 102 | out[0], out[1] 103 | ); 104 | src[0] = xx<`. 51 | 52 | .. list-table:: Existing encoder configuration files. 53 | :widths: 25 75 54 | :header-rows: 1 55 | 56 | * - Name 57 | - Description 58 | * - ``fast_10k.cfg`` 59 | - Reasonable compression performance & fast training 60 | * - ``medium_30k.cfg`` 61 | - Balance compression performance & training duration 62 | * - ``slow_100k.cfg`` 63 | - Best performance at the cost of a longer training 64 | * - ``perceptive.cfg`` 65 | - Optimize MSE and Wasserstein Distance for better subjective quality 66 | 67 | 68 | Tuning 69 | """""" 70 | 71 | The tuning parameters ``--tune`` allows to select the distortion metric(s) to be 72 | optimized. When the mode ``--tune=mse`` is selected, the Mean Squared Error is 73 | optimized. When ``--tune=wasserstein`` the distortion becomes a combination of 74 | MSE and Wasserstein Distance, as proposed in `Good, Cheap, and Fast: Overfitted 75 | Image Compression with Wasserstein Distortion, Ballé et al 76 | `_. 77 | 78 | .. attention:: 79 | 80 | Using ``--tune=wasserstein`` also introduces 7 features of common 81 | randomness, as described in the aforementioned Ballé's paper. 82 | 83 | Presets 84 | """"""" 85 | 86 | Cool-chic encoding works with tweakable presets *i.e.* different training 87 | parameters. Currently available presets are: 88 | 89 | * ``c3x_intra`` Inspired by `C3: High-performance and low-complexity neural 90 | compression from a single image or video, Kim et al 91 | `_. It is composed of two main phases: 92 | 93 | 1. additive noise model and softround for the latent quantization 94 | 95 | 2. Actual quantization with softround in the backward 96 | 97 | * ``debug`` Extremely fast preset with very bad performance only for debugging purposes. 98 | 99 | All presets feature a decreasing learning rate starting from ``start_lr``. 100 | 101 | The number of iterations in the first (and longest) phase of the ``c3x`` preset is 102 | set using ``n_itr``. 103 | 104 | In order to circumvent some training irregularities, it is possible to perform 105 | several independent encoding, keeping only the best one. We call that a training 106 | loop. The number of training loops is set by ``n_train_loops``. 107 | 108 | 109 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | :layout: landing 2 | :description: Cool-chic is a low-complexity neural image and video codec, 3 | offering image coding performance on par with VVC and fast CPU-only decoding. 4 | 5 | .. raw:: html 6 | 7 | 8 | 9 | 10 | .. role:: accent 11 | 12 | 13 | .. Cool-chic 14 | .. ========= 15 | 16 | .. image:: assets/coolchic-logo-light.png 17 | :height: 200 18 | :align: center 19 | :alt: Logo Cool-chic 20 | 21 | 22 | .. rst-class:: lead 23 | 24 | Cool-chic (pronounced :accent:`/kul ʃik/` as in French 🥖🧀🍷) is a 25 | low-complexity neural image and video codec based on overfitting. It offers 26 | image coding performance on par with H.266/VVC for 1000 multiplications per 27 | decoded pixel, allowing for fast CPU-only decoding. 28 | 29 | 30 | .. container:: buttons 31 | 32 | `Docs `_ 33 | `Release note `_ 34 | `Image coding performance `_ 35 | `Video coding performance `_ 36 | 37 | 38 | .. grid:: 1 1 1 2 39 | :gutter: 2 40 | :class-row: surface 41 | 42 | .. grid-item-card:: :octicon:`trophy` Great coding performance 43 | :link: https://orange-opensource.github.io/Cool-Chic/results/image/compression_performance.html 44 | 45 | Cool-chic offers visual quality similar to H.266/VVC with 30% less rate 46 | 47 | .. grid-item-card:: :octicon:`squirrel` Lightweight decoder 48 | :link: https://orange-opensource.github.io/Cool-Chic/results/image/decoding_complexity.html 49 | 50 | Cool-chic decoder only computes 1000 multiplications per decoded pixel 51 | 52 | .. grid-item-card:: :octicon:`rocket` Fast CPU-only decoder 53 | :link: https://orange-opensource.github.io/Cool-Chic/results/image/decoding_complexity.html 54 | 55 | Decode a 1280x720 image in 100 ms on CPU with our decoder written in C 56 | 57 | .. grid-item-card:: :octicon:`file-media` I/O format 58 | :link: https://orange-opensource.github.io/Cool-Chic/encoding/overview.html#i-o-format 59 | 60 | Encode PNG, PPM and YUV 420 & 444 files with a bitdepth of 8 to 16 61 | bits. 62 | 63 | | 64 | 65 | | 66 | 67 | .. image:: assets/logo_orange.png 68 | :height: 100 69 | :align: center 70 | :alt: Logo Orange 71 | 72 | | 73 | 74 | | 75 | 76 | .. toctree:: 77 | :maxdepth: 1 78 | :caption: Getting started 79 | :hidden: 80 | 81 | Quickstart 82 | What's new in 4.2? 83 | Example 84 | Literature 85 | 86 | .. toctree:: 87 | :maxdepth: 1 88 | :caption: Image coding 89 | :hidden: 90 | 91 | Overview 92 | Decoder configuration 93 | Encoder configuration 94 | Decoding a bitstream 95 | 96 | .. toctree:: 97 | :maxdepth: 1 98 | :caption: Video coding 99 | :hidden: 100 | 101 | Overview 102 | Decoder configuration 103 | Encoder configuration 104 | 105 | .. toctree:: 106 | :maxdepth: 2 107 | :caption: Compression performance 108 | :hidden: 109 | 110 | Image 111 | Video 112 | 113 | .. toctree:: 114 | :caption: Code Documentation 115 | :hidden: 116 | 117 | At a glance 118 | enc 119 | 120 | .. Decoder 121 | 122 | 123 | .. .. toctree:: 124 | .. :maxdepth: 1 125 | .. :caption: Code Documentation 126 | 127 | .. encoding_management 128 | .. models 129 | .. utils 130 | .. visu 131 | 132 | 133 | -------------------------------------------------------------------------------- /docs/source/getting_started/literature.rst: -------------------------------------------------------------------------------- 1 | Cool-chic literature 2 | ==================== 3 | 4 | There are several published papers describing and enhancing Cool-chic. Reading 5 | some of these papers might help understanding how Cool-chic works. 6 | 7 | Used in this repo 8 | """"""""""""""""" 9 | 10 | This repository is based on several papers successively enhancing Cool-chic. Check-out the `release history `_ to see previous versions of Cool-chic. 11 | 12 | 13 | .. list-table:: Papers implemented in this repository 14 | :widths: 15 15 25 45 15 | :header-rows: 1 16 | 17 | * - Date 18 | - Cool-chic version 19 | - Paper link 20 | - Key contributions 21 | * - 2025 Sep 22 | - ``4.2`` 23 | - `Philippe et al `_, `Ballé et al, CVPR `_ 24 | - Wasserstein Distance, Common Randomness 25 | * - 2025 July 26 | - ``4.1`` 27 | - `Ladune et al, `_ 28 | - Video coding, motion compensation 29 | * - 2025 Jan 30 | - ``4.0`` 31 | - `Leguay et al, ISCAS `_ 32 | - Video coding, RAFT guidance, motion cool-chic 33 | * - 2024 Nov 34 | - ``3.4`` 35 | - `Philippe et al, ISCAS `_ 36 | - Separable and symmetrical upsampling filters 37 | * - 2024 Mar 38 | - ``3.2`` 39 | - `Blard et al, EUSIPCO `_ 40 | - Fast decoder / Lighter Cool-chic image 41 | * - 2024 Feb 42 | - ``3.1`` 43 | - `Leguay et al, DCC `_ 44 | - 1st video coding with Cool-chic 45 | * - 2023 Dec 46 | - ``3.0`` 47 | - `Kim et al, CVPR `_ 48 | - Quantization approximation during training 49 | * - 2023 July 50 | - ``2.0`` 51 | - `Leguay et al, MMSP `_ 52 | - Learnable upsampling / CNN synthesis 53 | * - 2022 Dec 54 | - ``1.0`` 55 | - `Ladune et al, ICCV `_ 56 | - Initial Cool-chic paper 57 | 58 | Other papers 59 | """""""""""" 60 | 61 | Some other papers have enhanced or adapted Cool-chic to particular use-cases but 62 | have not (yet?) been integrated in this repository. 63 | 64 | .. list-table:: Other Cool-chic-related papers 65 | :widths: 15 25 60 66 | :header-rows: 1 67 | 68 | * - Date 69 | - Paper link 70 | - Key contributions 71 | * - 2025 July 72 | - `Wu et al, ICML `_ 73 | - Random synthesis parameters selecting through masking 74 | * - 2025 June 75 | - `Zhang et al, CVPR `_ 76 | - Lossless image coding 77 | * - 2025 Feb 78 | - `Ameen et al, `_ 79 | - Use Cool-chic to code a diffusion model feature space 80 | * - 2024 Oct 81 | - `Catania et al, ICIP `_ 82 | - Evaluate different distortion metrics 83 | * - 2024 Jan 84 | - `Liu et al `_ 85 | - Faster auto-regressive module 86 | * - 2024 Jan 87 | - `Ladune et al `_ 88 | - Fact sheet of the Cool-chic candidate to the `CLIC24 challenge `_ 89 | * - 2023 Dec 90 | - `Li et al, VCIP `_ 91 | - Faster auto-regressive module 92 | * - 2023 Dec 93 | - `Li et al, VCIP `_ 94 | - Remove the auto-regressive probability module 95 | * - 2023 Nov 96 | - `Zhang et al, IEEE SPL `_ 97 | - CNN-based post filter and SGA-based quantization 98 | * - 2023 Sep 99 | - `Le et al, ICASSP `_ 100 | - Adapt Cool-chic to DNA image coding 101 | * - 2023 June 102 | - `Le et al, MMSP `_ 103 | - Multiple description to handle noisy transmission channels 104 | -------------------------------------------------------------------------------- /coolchic/enc/utils/manager.py: -------------------------------------------------------------------------------- 1 | # Software Name: Cool-Chic 2 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 3 | # SPDX-License-Identifier: BSD 3-Clause "New" 4 | # 5 | # This software is distributed under the BSD-3-Clause license. 6 | # 7 | # Authors: see CONTRIBUTORS.md 8 | 9 | from dataclasses import dataclass, field, fields 10 | from enc.training.presets import AVAILABLE_PRESETS, Preset 11 | 12 | 13 | @dataclass 14 | class FrameEncoderManager(): 15 | """ 16 | All the encoding option for a frame (loss, lambda, learning rate) as well as some 17 | counters monitoring the training time, the number of training iterations or the number 18 | of loops already done. 19 | """ 20 | # ----- Encoding (i.e. training) options 21 | preset_name: str # Preset name, should be a key in AVAILABLE_PRESETS utils/encoding_management/presets.py 22 | start_lr: float = 1e-2 # Initial learning rate 23 | lmbda: float = 1e-3 # Rate constraint. Loss = D + lmbda R 24 | n_itr: int = int(1e5) # Maximum number of training iterations for a **single** phase 25 | n_loops: int = 1 # Number of training loop 26 | 27 | # ==================== Not set by the init function ===================== # 28 | # ----- Actual preset, instantiated from its name 29 | preset: Preset = field(init=False) # It contains the learning rate in the different phase 30 | 31 | # ----- Monitoring 32 | idx_best_loop: int = field(default=0, init=False) # Index of the loop which gives the best results (i.e. the best_loss) 33 | best_loss: float = field(default=1e6, init=False) # Overall best loss (for all loops) 34 | loop_counter: int = field(default=0, init=False) # Number of loops already done 35 | 36 | # Total training time and iterations counter including warm-up and multi loops 37 | total_training_time_sec: float = field(default=0., init=False) 38 | iterations_counter: int = field(default=0, init=False) 39 | # ==================== Not set by the init function ===================== # 40 | 41 | def __post_init__(self): 42 | assert self.preset_name in AVAILABLE_PRESETS, f'Preset named {self.preset_name} does not exist.' \ 43 | f' List of available preset:\n{list(AVAILABLE_PRESETS.keys())}.' 44 | 45 | self.preset = AVAILABLE_PRESETS.get(self.preset_name)(start_lr= self.start_lr, n_itr_per_phase=self.n_itr) 46 | 47 | flag_quantize_model = False 48 | for training_phase in self.preset.all_phases: 49 | if training_phase.quantize_model: 50 | flag_quantize_model = True 51 | assert flag_quantize_model, f'The selected preset ({self.preset_name}) does not include ' \ 52 | f' a training phase with neural network quantization.\n{self.preset.pretty_string()}' 53 | 54 | def record_beaten(self, candidate_loss: float) -> bool: 55 | """Return True if the candidate loss is better (i.e. lower) than the best loss. 56 | 57 | Args: 58 | candidate_loss (float): Current candidate loss. 59 | 60 | Returns: 61 | bool: True if the candidate loss is better than the best loss 62 | (i.e. candidate < best). 63 | """ 64 | return candidate_loss < self.best_loss 65 | 66 | def set_best_loss(self, new_best_loss: float): 67 | """Set the new best loss attribute. It automatically looks at the current loop_counter 68 | to fill the idx_best_loop attribute. 69 | 70 | Args: 71 | new_best_loss (float): The new best loss obtained at the current loop 72 | """ 73 | self.best_loss = new_best_loss 74 | self.idx_best_loop = self.loop_counter 75 | 76 | 77 | def pretty_string(self) -> str: 78 | """Return a pretty string formatting the data within the class""" 79 | ATTRIBUTE_WIDTH = 25 80 | VALUE_WIDTH = 80 81 | 82 | s = 'FrameEncoderManager value:\n' 83 | s += '--------------------------\n' 84 | for k in fields(self): 85 | # Do not print preset, it's quite ugly 86 | if k.name == 'preset': 87 | continue 88 | s += f'{k.name:<{ATTRIBUTE_WIDTH}}: {str(getattr(self, k.name)):<{VALUE_WIDTH}}\n' 89 | s += '\n' 90 | return s 91 | 92 | 93 | -------------------------------------------------------------------------------- /coolchic/enc/nnquant/expgolomb.py: -------------------------------------------------------------------------------- 1 | # Software Name: Cool-Chic 2 | # SPDX-FileCopyrightText: Copyright (c) 2023-2025 Orange 3 | # SPDX-License-Identifier: BSD 3-Clause "New" 4 | # 5 | # This software is distributed under the BSD-3-Clause license. 6 | # 7 | # Authors: see CONTRIBUTORS.md 8 | 9 | 10 | from enc.component.types import DescriptorNN 11 | from enc.nnquant.quantstep import get_q_step_from_parameter_name 12 | import torch 13 | from torch import Tensor, nn 14 | 15 | 16 | POSSIBLE_EXP_GOL_COUNT = { 17 | "arm": { 18 | "weight": torch.linspace(0, 12, 13, device="cpu"), 19 | "bias": torch.linspace(0, 12, 13, device="cpu"), 20 | }, 21 | "upsampling": { 22 | "weight": torch.linspace(0, 12, 13, device="cpu"), 23 | "bias": torch.linspace(0, 12, 13, device="cpu"), 24 | }, 25 | "synthesis": { 26 | "weight": torch.linspace(0, 12, 13, device="cpu"), 27 | "bias": torch.linspace(0, 12, 13, device="cpu"), 28 | }, 29 | } 30 | 31 | 32 | @torch.no_grad() 33 | def measure_expgolomb_rate( 34 | q_module: nn.Module, q_step: DescriptorNN, expgol_cnt: DescriptorNN 35 | ) -> DescriptorNN: 36 | """Get the rate associated with the current parameters. 37 | 38 | Returns: 39 | DescriptorNN: The rate of the different modules wrapped inside a dictionary 40 | of float. It does **not** return tensor so no back propagation is possible 41 | """ 42 | # Concatenate the sent parameters here to measure the entropy later 43 | sent_param: DescriptorNN = {"bias": [], "weight": []} 44 | rate_param: DescriptorNN = {"bias": 0.0, "weight": 0.0} 45 | 46 | param = q_module.get_param() 47 | # Retrieve all the sent item 48 | for parameter_name, parameter_value in param.items(): 49 | current_q_step = get_q_step_from_parameter_name(parameter_name, q_step) 50 | # Current quantization step is None because the module is not yet 51 | # quantized. Return an all zero rate 52 | if current_q_step is None: 53 | return rate_param 54 | 55 | # Quantization is round(parameter_value / q_step) * q_step so we divide by q_step 56 | # to obtain the sent latent. 57 | current_sent_param = (parameter_value / current_q_step).view(-1) 58 | 59 | if ".weight" in parameter_name: 60 | sent_param["weight"].append(current_sent_param) 61 | elif ".bias" in parameter_name: 62 | sent_param["bias"].append(current_sent_param) 63 | else: 64 | print( 65 | 'Parameter name should include ".weight" or ".bias" ' 66 | f"Found: {parameter_name}" 67 | ) 68 | return rate_param 69 | 70 | # For each sent parameters (e.g. all biases and all weights) 71 | # compute their cost with an exp-golomb coding. 72 | for k, v in sent_param.items(): 73 | # If we do not have any parameter, there is no rate associated. 74 | # This can happens for the upsampling biases for instance 75 | if len(v) == 0: 76 | rate_param[k] = 0.0 77 | continue 78 | 79 | # Current exp-golomb count is None because the module is not yet 80 | # quantized. Return an all zero rate 81 | current_expgol_cnt = expgol_cnt[k] 82 | if current_expgol_cnt is None: 83 | return rate_param 84 | 85 | # Concatenate the list of parameters as a big one dimensional tensor 86 | v = torch.cat(v) 87 | 88 | # This will be pretty long! Could it be vectorized? 89 | rate_param[k] = exp_golomb_nbins(v, count=current_expgol_cnt) 90 | 91 | return rate_param 92 | 93 | 94 | def exp_golomb_nbins(symbol: Tensor, count: int = 0) -> Tensor: 95 | """Compute the number of bits required to encode a Tensor of integers 96 | using an exponential-golomb code with exponent ``count``. 97 | 98 | Args: 99 | symbol: Tensor to encode 100 | count (int, optional): Exponent of the exp-golomb code. Defaults to 0. 101 | 102 | Returns: 103 | Number of bits required to encode all the symbols. 104 | """ 105 | 106 | # We encode the sign equiprobably at the end thus one more bit if symbol != 0 107 | nbins = ( 108 | 2 * torch.floor(torch.log2(symbol.abs() / (2**count) + 1)) 109 | + count 110 | + 1 111 | + (symbol != 0) 112 | ) 113 | res = nbins.sum() 114 | return res 115 | --------------------------------------------------------------------------------